iosobjective-cswiftuiview

Converting points between view coordinate systems


I'm having a difficult time understanding the difference between convert(_:to:) and convert(_:from:) for some reason.

Let's say I have two views (superView and subview) and a root view:

let superView = UIView(frame: CGRect(origin: .init(x: 25, y: 25), size: CGSize(width: 100, height: 100)))
rootView.addSubview(view)

let subview = UIView(frame: CGRect(origin: .init(x: 25, y: 25), size: .init(width: 50, height: 50)))
superView.addSubview(subview)

convert(_:to:) converts a point from the receiver’s coordinate system to that of the specified view, according to the documentation:

let convertToWindow = subview.convert(subview.bounds, to: window)
// {x 50 y 50 w 50 h 50 }

convert(_:from:) converts a point from the coordinate system of a given view to that of the receiver, according to the documentation:

let convertFromWindow = subview.convert(subview.bounds, from: window)
// {x -50 y -50 w 50 h 50 }

Is the "receiver" subview in this case? If so, I think I sort of understand convert(_:from:) to be converting subview's coordinates with respect to is own coordinates (and not its super view) to the position within window, which is why it's going from {x 0 y 0 w 50 h 50 } to {x 50 y 50 w 50 h 50 }.

However, what is convert(_:from:) doing when it's converting subviews.bound that already uses the coordinate system of subview? Why doesn't subview.convert(subview.bounds, from: window) return {x 0 y 0 w 50 h 50 }?

Finally, if the convert method merely converts a point or a bound to and from a view, why does the instance the method belongs to make a difference in the result of the conversion? For example, subview.convert(subview.bounds, to: window) and superView.convert(subview.bounds, to: window) yield different results.


Solution

  • Yes, in an expression like subview.convert..., we call subview the "receiver" — it is the object to which the convert message is sent, so it receives that message.

    Why doesn't subview.convert(subview.bounds, from: window) return {x 0 y 0 w 50 h 50 }?

    The mental mistake you're making here is that you think subview.bounds somehow pins this value to subview. It doesn't. The first parameter is merely some numbers. The convert method doesn't know where you got those numbers from. That is why you have to tell it where you got them — with the second parameter:

    why does the instance the method belongs to make a difference in the result of the conversion

    Because that is the other view in the story:

    Remember, the first parameter is just some numbers. You can get them from anywhere you want, including the inside of your head, but you won't get the "right" answer if you lie about this in the rest of the expression — as some of your examples do.