0

I have 2 UIImageViews in a ViewController and I'm trying to work out when they intersect.

imageViewA: is in my storyboard view, with constraints, and is in a hierarchy of views as follows:

- Background
-- Images
--- imageViewA

imageViewB: is created dynamically and is dragged around the screen using a UIPanGestureRecognizer.

When the drag ends, I want to check if imageViewB intersects with imageViewB. I used the intersects function, but don't get the results I expect, I suppose because imageViewA is in a hierachy of views, which means it's in a different coordinate system. So I want to convert both views to the same coordinate system. How I can do this?

I've tried the following:

let frameA = imageViewA.convert(imageViewA.frame, to: self.view)
let frameB = imageViewB.convert(imageViewB.frame, to: self.view)

But it doesn't give me the results I expect, which frameB having a much larger Y coordinate.

Do I need to do something like this:

let frameA = imageViewA.superview?.superview?.convert(imageViewA.superview?.superview?.frame, to: self.view)

There are other questions covering conversion to coordinate systems, but they don't seem to tackle what to do when the view is in a hierarchy.

mcfroob
  • 1,044
  • 1
  • 11
  • 13
  • hmm the code you show seems like it should work to me :/ this post should help : http://stackoverflow.com/questions/8465659/understand-convertrecttoview-convertrectfromview-convertpointtoview-and – Sean Lintern Jan 26 '17 at 13:06

2 Answers2

2

Your problem is that imageViewA.frame is in the geometry (coordinate system) of imageViewA.superview, but UIView.convert(_ rect: to view:) expects rect to be in the geometry of imageViewA.

UPDATE

The simplest solution is to convert imageViewA.bounds (which is in imageViewA's geometry) directly to imageViewB's geometry, and then see if it intersects imageViewB.bounds, which is also in imageViewB's geometry:

let aInB = imageViewA.convert(imageViewA.bounds, to: imageViewB)
if aInB.intersects(imageViewB.bounds) {
    ...

ORIGINAL

The simplest solution is to convert imageViewA.bounds, which is in imageViewA's own geometry:

let frameA = imageViewA.convert(imageViewA.bounds, to: self.view)
let frameB = imageViewB.convert(imageViewB.bounds, to: self.view)
rob mayoff
  • 375,296
  • 67
  • 796
  • 848
0

I misunderstood the convert function. Just in case it's useful for anyone else, the solution looks like this:

let convertedFrameB = frameA.superview?.convert(frameA.frame, from self.view)

if(convertedFrameB.intersects(frameA.frame) {...
   ...
}

Here's an extension that might be useful:

extension UIView {

func intersectsIgnoringCoordinateSpace(_ view2: UIView) -> Bool {
    let frameOne = self.convert(self.bounds, to: self.topLevelView)
    let frameTwo = view2.convert(self.bounds, to: self.topLevelView)

    return frameOne.intersects(frameTwo)
}

var topLevelView: UIView? {
    get {
        var topView = self.superview

        while(topView?.superview != nil) {
            topView = topView?.superview
        }
        return topView
    }
}
mcfroob
  • 1,044
  • 1
  • 11
  • 13