Hi all,
I'm sure I'm doing something wrong with UIView.convert(), so maybe you can set me on the right path here. I'm working in Swift 3.
For simplicity's sake, let's say I have a UIViewController which contains nothing more than a UIStackView with two UIView subviews, leftView and rightView, side by side. Assume leftView and rightView are exactly the same size—let's say 200 by 200 points.
I want to get the origin of these subviews with respect to the view controller's origin. In other words, in my view controller, I call
let leftViewOrigin: CGPoint = leftView.convert(leftView.frame.origin, to: self.view)And I get the point I expect for leftView, some horizontal and vertical offset—say (16, 100)—from the view controller's view's origin. Great!
If I then do the same to get the origin of the rightView:
let rightViewOrigin: CGPoint = rightView.convert(rightView.frame.origin, to: self.view)I should get the same CGPoint as I did for leftView, plus a horizontal offset equal to the width of leftView, or (216, 100)—216 because 16 from leftViewOrigin.x plus the 200 point width of leftView. In other words, I expect to get the point corresponding to the top-left corner of rightView.
Instead, I get the point corresponding to the top-right corner of rightView—in this example, (416, 100), where 416 is the 16 from leftViewOrigin.x, plus the 200-point width of leftView, plus the 200-point width of rightView.
I've put a sample project up on GitHub to show this behaviour.
For the record, I see the same behaviour regardless of whether or not I use convert(to:) or convert(from:), and (assuming this is the main, full-screen, view controller), whether I convert to self.view or nil.
On the off chance that I'm doing this correctly and there's a bug, I will file a radar.
The point you pass needs to be in the coordinate system of the view that you are requesting do the conversion. Your code is requesting the frame.origin of rightView as if rightView were a subview of itself.
The simplest fix is to change <view>.frame.origin in your code to <view>.bounds.origin. This "works" for leftView because leftView.frame.origin is likely the same value as leftView.bounds.origin.