Detecting if UIView is intersecting other UIViews

14,430

Solution 1

First, create some array that stores the frames of all of your UIViews and their associated reference.

Then, potentially in a background thread, you can run some collision testing using what's in the array. For some simple collision testing for rectangles only, check out this SO question: Simple Collision Algorithm for Rectangles

Hope that helps!

Solution 2

There's a function called CGRectIntersectsRect which receives two CGRects as arguments and returns if the two given rects do intersect. And UIView has subviews property which is an NSArray of UIView objects. So you can write a method with BOOL return value that'll iterate through this array and check if two rectangles intersect, like such:

- (BOOL)viewIntersectsWithAnotherView:(UIView*)selectedView {

    NSArray *subViewsInView = [self.view subviews];// I assume self is a subclass
                                       // of UIViewController but the view can be
                                       //any UIView that'd act as a container 
                                       //for all other views.

     for(UIView *theView in subViewsInView) {

       if (![selectedView isEqual:theView])
           if(CGRectIntersectsRect(selectedView.frame, theView.frame))  
              return YES;
    }

  return NO;
}

Solution 3

To Achieve the same thing in swift as per the accepted answer then here is the function. Readymade Code. Just copy and use it as per the steps. By the way I am using Xcode 7.2 with Swift 2.1.1.

func checkViewIsInterSecting(viewToCheck: UIView) -> Bool{
    let allSubViews = self.view!.subviews //Creating an array of all the subviews present in the superview.
    for viewS in allSubViews{ //Running the loop through the subviews array
        if (!(viewToCheck .isEqual(viewS))){ //Checking the view is equal to view to check or not
            if(CGRectIntersectsRect(viewToCheck.frame, viewS.frame)){ //Checking the view is intersecting with other or not
                return true //If intersected then return true
            }
        }  
    }
    return false //If not intersected then return false
}

Now call this function as per the following -

let viewInterSected = self.checkViewIsInterSecting(newTwoPersonTable) //It will give the bool value as true/false. Now use this as per your need

Thanks.

Hope this helped.

Solution 4

In my case the views were nested, so I did this (works with both nested and not):

extension UIView {
    func overlaps(other view: UIView, in viewController: UIViewController) -> Bool {
        let frame = self.convert(self.bounds, to: viewController.view)
        let otherFrame = view.convert(view.bounds, to: viewController.view)
        return frame.intersects(otherFrame)
    }
}

Hope it helps.

Share:
14,430

Related videos on Youtube

0xSina
Author by

0xSina

umadbr0

Updated on June 04, 2022

Comments

  • 0xSina
    0xSina almost 2 years

    I have a bunch of UIViews on the screen. I would like to know what's the best to way to check if a particular view (which I have reference to) is intersection ANY other views. The way I am doing it right now is, iterating though all the subviews and check one by one if there's an intersection between the frames.

    This doesn't seem very efficient. Is there a better way to do this?

    • Mike Weller
      Mike Weller
      Have you tried running the code in Instruments? I think you'll find it's perfectly fast and efficient. The code for rect intersection is just simple math so I can't see it being a problem in terms of speed, even with hundreds of views.
  • Jonny
    Jonny over 12 years
    +(BOOL)viewIntersectsWithAnotherView:(UIView*)selectedView inView:(UIView*)containerView { for (UIView* theView in containerView.subviews) { if ([selectedView isEqual:theView]) continue; if (CGRectIntersectsRect(selectedView.frame, theView.frame)) { return YES; } } return NO; }
  • Jonny
    Jonny over 12 years
    Couldn't get code formatting in comments. :-P Anyway a bit of refactoring + code fixes.
  • Mikayil Abdullayev
    Mikayil Abdullayev over 12 years
    You're right Jonny I should leave the iteration. So I've changed the code to be more efficient.
  • katzenhut
    katzenhut over 10 years
    @MikeJM - foreach in objc/cocoa code? must be a typo, right? Great answer nonetheless, should be the accepted one. +1
  • Mikayil Abdullayev
    Mikayil Abdullayev over 10 years
    Right, @katzenhut, seems I confused with the C# syntax. Thanks for the correction.
  • Stephan
    Stephan over 10 years
    instead of CGRectIntersectsRect you can use NSIntersectsRect
  • kabiroberai
    kabiroberai about 8 years
    A more swift-ey approach would be replacing CGRectIntersectsRect(viewToCheck.frame, viewS.frame) with viewToCheck.frame.intersects(viewS.frame)
  • aznelite89
    aznelite89 almost 7 years
    worked but in swift 3 , kindly use view.frame.intersects(secondView.frame) {...}