2017-04-05 8 views
2

2以上のビュー(UIView)の任意のセットが与えられているので、それらのビューの(最も近い)共通の親を決定したいと考えています。 Swiftでこれに対して最も効率的なアルゴリズムは何ですか?これらの階層に基づいてSwiftの共通の親ビュー

    ┌─────┐             
        │ A │             
        └─────┘             
         ▲              
      ┌────────────┴────────────┐           
      │       │           
     ┌─────┐     ┌─────┐    ┌─────┐    
     │ B │     │ C │    │ X │    
     └─────┘     └─────┘    └─────┘    
      ▲       ▲      ▲     
    ┌──────┴──────┐   ┌──────┴──────┐    │     
    │    │   │    │    │     
┌─────┐  ┌─────┐  ┌─────┐  ┌─────┐   ┌─────┐  ┌─────┐ 
│ D │  │ E │  │ F │  │ G │   │ Y │  │ Z │ 
└─────┘  └─────┘  └─────┘  └─────┘   └─────┘  └─────┘ 
  • 何の景色が設けられていない場合は、nilを返します。
  • ビューが1つの場合は、superviewまたはnilを返します。
  • ビューにsuperview(「A」、「X」、または「Z」など)がない場合は、nilを返します。
  • ビューが同じ階層(「A」または「X」階層など)に属していない場合は、nilを返します。

例:

Larmeの提案@に基づいて
// 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

、ここで私が作ってみたものです。すべてのケースをカバーする必要があります。コメントは感謝します。

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秒) –

関連する問題