检测UIView是否与其他UIView相交

6

屏幕上有许多UIView。我想知道检查特定视图(我已经引用)是否与任何其他视图相交的最佳方法是什么。我现在所做的方式是,遍历所有子视图并逐个检查框架之间是否存在交集。

这似乎不是很有效率。有更好的方法吗?


1
你尝试在Instruments中运行代码了吗?我认为您会发现它非常快和高效。矩形相交的代码只是简单的数学,因此我认为即使有数百个视图,速度方面也不会出现问题。 - Mike Weller
4个回答

37

有一个叫做CGRectIntersectsRect的函数,它接收两个CGRect作为参数,并返回这两个矩形是否相交。而UIView有一个子视图属性subviews,是一个UIView对象的NSArray。因此,您可以编写一个带有BOOL返回值的方法,该方法将遍历此数组并检查两个矩形是否相交,例如:

- (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;
}

1
+(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
1
无法在注释中获取代码格式。:-P 无论如何,进行了一些重构和代码修复。 - Jonny
你说得对,乔尼,我应该离开这个迭代。所以我改变了代码,使其更加高效。 - Mikayil Abdullayev
@MikeJM - 在 Objective-C/Cocoa 代码中使用 foreach?一定是打错了吧?不过回答很棒,应该被采纳。+1 - katzenhut
没错,@katzenhut,看来我把C#的语法搞混了。感谢你的纠正。 - Mikayil Abdullayev
1
你可以使用 NSIntersectsRect 替代 CGRectIntersectsRect - Stephan

3

在我的情况下,视图是嵌套的,所以我做了这个(适用于嵌套和非嵌套):

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)
    }
}

希望这有所帮助。

3
要在 Swift 中实现与已接受答案相同的内容,可以使用以下函数。准备好的代码。只需按照步骤复制并使用即可。顺便说一下,我正在使用带有 Swift 2.1.1 的 Xcode 7.2。
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
}

现在,请按照以下方式调用此函数 -
let viewInterSected = self.checkViewIsInterSecting(newTwoPersonTable) //It will give the bool value as true/false. Now use this as per your need

谢谢。

希望这有所帮助。


1
一种更加简洁的方法是将 CGRectIntersectsRect(viewToCheck.frame, viewS.frame) 替换为 viewToCheck.frame.intersects(viewS.frame) - kabiroberai
已经在 Swift 3 中运行, 请使用 view.frame.intersects(secondView.frame) {...}。 - aznelite89

0
首先,创建一些数组来存储所有UIView框架及其相关引用。
然后,可能在后台线程中,您可以使用数组中的内容运行一些碰撞测试。对于仅针对矩形的简单碰撞测试,请查看此SO问题:Simple Collision Algorithm for Rectangles 希望这有所帮助!

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接