Understand convertRect:toView:, convertRect:FromView:, convertPoint:toView: and convertPoint:fromView: methods
Each view has its own coordinate system - with an origin at 0,0 and a width and height. This is described in the bounds
rectangle of the view. The frame
of the view, however, will have its origin at the point within the bounds rectangle of its superview.
The outermost view of your view hierarchy has it's origin at 0,0 which corresponds to the top left of the screen in iOS.
If you add a subview at 20,30 to this view, then a point at 0,0 in the subview corresponds to a point at 20,30 in the superview. This conversion is what those methods are doing.
Your example above is pointless (no pun intended) since it converts a point from a view to itself, so nothing will happen. You would more commonly find out where some point of a view was in relation to its superview - to test if a view was moving off the screen, for example:
CGPoint originInSuperview = [superview convertPoint:CGPointZero fromView:subview];
The "receiver" is a standard objective-c term for the object that is receiving the message (methods are also known as messages) so in my example here the receiver is superview
.
I always find this confusing so I made a playground where you can visually explore what the convert
function does. This is done in Swift 3 and Xcode 8.1b:
import UIKitimport PlaygroundSupportclass MyViewController: UIViewController { override func viewDidLoad() { super.viewDidLoad() // Main view view.backgroundColor = .black view.frame = CGRect(x: 0, y: 0, width: 500, height: 500) // Red view let redView = UIView(frame: CGRect(x: 20, y: 20, width: 460, height: 460)) redView.backgroundColor = .red view.addSubview(redView) // Blue view let blueView = UIView(frame: CGRect(x: 20, y: 20, width: 420, height: 420)) blueView.backgroundColor = .blue redView.addSubview(blueView) // Orange view let orangeView = UIView(frame: CGRect(x: 20, y: 20, width: 380, height: 380)) orangeView.backgroundColor = .orange blueView.addSubview(orangeView) // Yellow view let yellowView = UIView(frame: CGRect(x: 20, y: 20, width: 340, height: 100)) yellowView.backgroundColor = .yellow orangeView.addSubview(yellowView) // Let's try to convert now var resultFrame = CGRect.zero let randomRect: CGRect = CGRect(x: 0, y: 0, width: 100, height: 50) /* func convert(CGRect, from: UIView?) Converts a rectangle from the coordinate system of another view to that of the receiver. */ // The following line converts a rectangle (randomRect) from the coordinate system of yellowView to that of self.view: resultFrame = view.convert(randomRect, from: yellowView) // Try also one of the following to get a feeling of how it works: // resultFrame = view.convert(randomRect, from: orangeView) // resultFrame = view.convert(randomRect, from: redView) // resultFrame = view.convert(randomRect, from: nil) /* func convert(CGRect, to: UIView?) Converts a rectangle from the receiver’s coordinate system to that of another view. */ // The following line converts a rectangle (randomRect) from the coordinate system of yellowView to that of self.view resultFrame = yellowView.convert(randomRect, to: view) // Same as what we did above, using "from:" // resultFrame = view.convert(randomRect, from: yellowView) // Also try: // resultFrame = orangeView.convert(randomRect, to: view) // resultFrame = redView.convert(randomRect, to: view) // resultFrame = orangeView.convert(randomRect, to: nil) // Add an overlay with the calculated frame to self.view let overlay = UIView(frame: resultFrame) overlay.backgroundColor = UIColor(white: 1.0, alpha: 0.9) overlay.layer.borderColor = UIColor.black.cgColor overlay.layer.borderWidth = 1.0 view.addSubview(overlay) }}var ctrl = MyViewController()PlaygroundPage.current.liveView = ctrl.view
Remember to show the Assistant Editor (⎇⌘⏎) in order to see the views, it should look like this:
Feel free to contribute more examples here or in this gist.
Here's an explanation in plain English.
When you want to convert the rect of a subview (aView
is a subview of [aView superview]
) to the coordinate space of another view (self
).
// So here I want to take some subview and put it in my view's coordinate space_originalFrame = [[aView superview] convertRect: aView.frame toView: self];