Last active
December 26, 2020 14:46
-
-
Save lamprosg/80ea6a97700c2c16636b444702d19844 to your computer and use it in GitHub Desktop.
(iOS) Find common ancestor of two UIViews
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//Time complexity:O(N), Space complexity: (1) | |
func findCommonSuper(_ view1:inout UIView, _ view2:inout UIView) -> UIView? { | |
//Get the level of the 2 views | |
var level1 = findLevel(view1) | |
var level2 = findLevel(view2) | |
/****/ | |
//Find the 2 views for the same level | |
if level1 > level2 { | |
var dif = level1-level2 | |
while dif > 0 { | |
view1 = view1.superview! | |
dif -= 1 | |
} | |
} else if level1 < level2 { | |
var dif = level2-level1 | |
while dif > 0 { | |
view2 = view2.superview! | |
dif -= 1 | |
} | |
} | |
/****/ | |
//Iterate upwords until the common ancestor is found | |
while view1 != view2 { | |
//No ancestor if superview is nil | |
if view1.superview == nil || view2.superview == nil { | |
return nil | |
} | |
//Get the superview | |
view1 = view1.superview! | |
view2 = view2.superview! | |
} | |
//we must have reached the common superview | |
if view1 == view2 { | |
return view1 | |
} | |
return nil | |
} | |
//Returns how deep in the tree of subviews the view is. | |
func findLevel(_ view:UIView) -> Int { | |
var level = 0 | |
var view = view | |
while view.superview != nil { | |
view = view.superview! | |
level += 1 | |
} | |
return level | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
extension UIView { | |
func nearestCommonSuperviewWith(other: UIView) -> UIView? { | |
//Starting from self view | |
var nearestAncestor: UIView? = self | |
//Get the superview until the other view is descendant of the view we ended up | |
while let testView = nearestAncestor, !other.isDescendant(of: testView) { | |
nearestAncestor = testView.superview | |
} | |
return nearestAncestor | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment