Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Shared ancestor between two views

What is the most efficient way to find the lowest common ancestor between two UIView instances?

Short of implementing Lowest Common Ancestor, are there any UIKit APIs that can be leveraged to find it?

NSView has ancestorSharedWithView: so I suspect this might be added sooner than later to iOS.

I'm currently using this quick and dirty solution, which is inefficient if the given view isn't a sibling or direct ancestor.

- (UIView*)lyt_ancestorSharedWithView:(UIView*)aView
{
    if (aView == nil) return nil;
    if (self == aView) return self;
    if (self == aView.superview) return self;
    UIView *ancestor = [self.superview lyt_ancestorSharedWithView:aView];
    if (ancestor) return ancestor;
    return [self lyt_ancestorSharedWithView:aView.superview];
}

(for those implementing a similar method, the unit tests of the Lyt project might be helpful)

like image 930
hpique Avatar asked Mar 26 '14 15:03

hpique


2 Answers

It's not too hard, using -isDescendantOfView:.

- (UIView *)my_ancestorSharedWithView:(UIView *)aView
{
    UIView *testView = self;
    while (testView && ![aView isDescendantOfView:testView])
    {
        testView = [testView superview];
    }
    return testView;
}
like image 92
Carl Lindberg Avatar answered Sep 21 '22 02:09

Carl Lindberg


Swift 3:

extension UIView {
    func findCommonSuperWith(_ view:UIView) -> UIView? {

        var a:UIView? = self
        var b:UIView? = view
        var superSet = Set<UIView>()
        while a != nil || b != nil {

            if let aSuper = a {
                if !superSet.contains(aSuper) { superSet.insert(aSuper) }
                else { return aSuper }
            }
            if let bSuper = b {
                if !superSet.contains(bSuper) { superSet.insert(bSuper) }
                else { return bSuper }
            }
            a = a?.superview
            b = b?.superview
        }
        return nil

    }
} 
like image 41
Or Ron Avatar answered Sep 23 '22 02:09

Or Ron