Converting frames between view coordinate systems

Christoffer Winterkvist
hyperoslo
Published in
4 min readMar 6, 2018
Iswanto Arifhttps://unsplash.com/photos/OJ74pFtrYi0

Knowing the exact position of a subview is a technique that can come in handy on multiple occasions. You might want to know if the view is visible to the user, perform an animation from the views initial position or restore the view to its original destination. There are plenty of use cases for this; you can probably think of dozens more. However, when you want to do this you can’t simply rely on the target view’s frame as that is only a part of its super-views coordinate system, this quickly causes issues depending on how you compose your view hierarchy. Lucky for us, both UIView and NSView have some methods to give us the desired results. If you read a previous article of mine about how frames work on macOS, you might remember that we briefly touched on coordinate systems.

So let’s dive in to see how we can convert frames between different coordinate systems.

The first thing that we create is a UIWindow. We give it a frame and later assign a root view to our newly created window. We give the root view a color so that we can more easily see where on view start and the other one begins.

Next is your view, this is meant to represent your custom view implementation. It gets a frame and a color and is added as a subview on the window. So far we have only written code to get the example up and running, nothing new and exciting.

Last but not least is the subview, it gets the same treatment as the other ones and is added as a subview to the view.

Now that we have our scenario set up let’s look at the method that the whole article is about, the convert(CGRect, to: UIView?) method.

If we examine the values that we get back from just accessing the view’s frame. It is the correct value inside the views coordinates space, but that doesn’t make it universally correct when trying to assemble these kinds of values in a context that expands to the outside of the views coordinate space.

The view frame without converting.

What we want to achieve is to know the views exact position on the screen, not the position within the subview.

So by passing the current frame and pointing it to the desired coordinate space, we can now get the measurements that we need. You can switch to any coordinate system that you like; I picked the window as that has been the most relevant for me in the past.

The view frame converted to the windows coordinate system.

When doing this in your implementation, accessing the view’s window is trivial. All UIView’s has an optional reference to the window it belongs to, if this value is nil it means that the view hasn’t been added to a window yet.

As a side note, this is just the tip of the iceberg; there are more of these kinds of methods that take points instead of a frame. Have a look at UICoordinateSpace for more information.

https://developer.apple.com/documentation/uikit/uicoordinatespace

The reason why these methods are also available on UIWindow is that it inherits from UIView which in turn conforms to UICoordinateSpace.

As you can see, this is straight-forward yet powerful, but what about macOS. Let’s have a look at another example with some macOS code.

The technique itself remains the same, as well as the result when converting. The only noticeable difference between the two examples is that it uses an NSView to represent the window. The reason for this is that NSWindow does not conform to PlaygroundLiveViewable.

Even if this might seem niché, this technique holds enormous value when reasoning about how to solve specific situations. I’ve used this method when optimizing scrolling performance of both scroll views and collection views, opting out from performing layout operations if the view is not visible on the screen. I’ve also used these kinds of values to define start and end positions for core animations. I’m sure that you can come up with more scenarios, the point is that knowing the technique expands your toolbox and the bigger toolbox that you acquired, the more natural is to find the best solution for your problem.

Hope you found this useful, for me, this has been life-saver countless times.

--

--

Christoffer Winterkvist
hyperoslo

random hero at @fink-oslo by day, cocoa vigilante by night, dad at dawn. my life is awesome. Previously @hyperoslo