2017-04-05 22 views
2

给定任意一组的2个或更多视图(UIView),我想确定这些视图的(最接近的)共同父项是什么。 Swift中最有效的算法是什么?Swift中的共同父视图

基于这些层次:

    ┌─────┐             
        │ A │             
        └─────┘             
         ▲              
      ┌────────────┴────────────┐           
      │       │           
     ┌─────┐     ┌─────┐    ┌─────┐    
     │ B │     │ C │    │ X │    
     └─────┘     └─────┘    └─────┘    
      ▲       ▲      ▲     
    ┌──────┴──────┐   ┌──────┴──────┐    │     
    │    │   │    │    │     
┌─────┐  ┌─────┐  ┌─────┐  ┌─────┐   ┌─────┐  ┌─────┐ 
│ D │  │ E │  │ F │  │ G │   │ Y │  │ Z │ 
└─────┘  └─────┘  └─────┘  └─────┘   └─────┘  └─────┘ 
  • 如果没有提供意见,返回nil。
  • 如果提供1个视图,则返回superview或零。
  • 如果任何视图没有superview(例如“A”,“X”或“Z”),则返回nil。
  • 如果视图不属于同一层次结构(例如“A”或“X”层次结构),则返回nil。

例子:基于

// no views 
[].commonParent()  // nil 
// 1 view 
[D].commonParent()  // B 
// siblings 
[D,E].commonParent() // B 
// child/parent 
[D,B].commonParent() // A 
// cousins 
[D,F].commonParent() // A 
// > 2 views 
[D,E,F].commonParent() // A 
// with root view 
[D,A].commonParent() // nil 
// unrelated hierarchies 
[D,Y].commonParent() // nil 
// unrelated view 
[D,Z].commonParent() // nil 
+0

是的,'UIView'。尽管这同样适用于NSView。 –

+0

具体而言,我正在寻找一种使用Swift的算法(即不是Objective-C)。据我所知,UIKit中没有任何东西可以帮助确定一个共同的父视图。 –

+0

为什么不使用Objective-C?由于它是关于UIKit的,可以采用类似的方法。 UIView有一个方法'isDescendantOfView:'可以用于这个。因此,在通过第一个视图的'superView'进行迭代时,检查另一个是否是后代。 – Larme

回答

0

上@ Larme的建议,这里是我想出。应该涵盖所有情况。评论赞赏。

extension Collection where Iterator.Element:UIView {  

    func commonParent() -> UIView? { 

     // Must be at least 1 view 
     guard let firstView = self.first else { 
      return nil 
     } 

     // If only 1 view, return it's superview, or nil if already root 
     guard self.count > 1 else { 
      return firstView.superview 
     } 

     // All views must have a superview, otherwise return nil 
     guard self.filter({ $0.superview == nil }).count == 0 else { 
      return nil 
     } 

     // Find the common parent 
     var superview = firstView.superview 
     while superview != nil { 
      if self.reduce(true, { $1.isDescendant(of: superview!) && $1 != superview! }) { 
       // If all views are descendent of superview return common parent 
       return superview 
      } else { 
       // else go to next superview and test that 
       superview = superview?.superview 
      } 
     } 
     // else, there is no common parent 
     return nil 
    } 
} 
+0

我已经测试过这个性能,而且速度非常快。 (使用> 10个节点,执行10,000个查询= 0.022秒。) –

相关问题