Skip to content

Instantly share code, notes, and snippets.

@lamprosg
Last active December 26, 2020 14:46
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save lamprosg/80ea6a97700c2c16636b444702d19844 to your computer and use it in GitHub Desktop.
Save lamprosg/80ea6a97700c2c16636b444702d19844 to your computer and use it in GitHub Desktop.
(iOS) Find common ancestor of two UIViews
//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
}
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