2016-03-23 14 views
3

Apple'ın C döngülerinden hoşlanmadığı, ancak iyi bir yaklaşım sağlamadığı anlaşılıyor (veya bulamadım).Swift 3: (;;) döngüsü için bunu nasıl yazılır

for var parentView = view; parentView != nil; parentView = parentView.parent { 
    ... 
} 

Nasıl Swift 3 şekilde bunu yazmak için: Ben UI hiyerarşisindeki köküne bazı görünümden gitmek için böyle döngü var? Bir sonraki while için değil, blok sonunda grubuna döngü ilerleme şeyler istiyorsanız

var parentView: View! = view 
while parentView != nil { 
    // Do stuff 
    parentView = parentView.parent 
} 

, böyle, defer kullanabilirsiniz:

+1

It ** değil Apple ** C döngülerinden hoşlanmayanlar, ama [Erica Sadun] (https://github.com/apple/swift-evolution/blob/master/proposals/0007-remove-c-style-for-loops.md), Andy Matuschak (Khan Academy), Keith Smiley (Lyft) ve posta listesinde diğerleri. Chris Lattner (Apple) sadece onlara açık. Sonunda komite bunu kabul etti. – adib

+0

Lütfen soruyu soruna "Güncelle" olarak eklemeyin. Kendi çözümünüzü paylaşmak isterseniz, bir cevap yazabilirsiniz. – FelixSFD

+1

@FelixSFD tavsiye için teşekkürler, – brigadir

cevap

2

Bu Swift 3 bunu yapmanın bir yolu olurdu :

var parentView: View! = view 
while parentView != nil { 
    defer { parentView = parentView.parent }   
    // Do stuff 
} 

Eğer parentView kapsamını sınırlamak istiyorsanız, bir do blokta her şeyi sarabiliriz:

do { 
    var parentView: View! = view 
    while parentView != nil { 
     defer { parentView = parentView.parent }   
     // Do stuff 
    } 
} 

Ama bu gibi benzer döngüler için yeni bir cins işlev tanımlamak böylece oldukça ayrıntılı açıklanmıştır:

func kindaCStyleLoop<T>(first: T, obtainNext: T -> T?, action: T ->()) { 
    var current: T! = first 
    repeat { 
     action(current) 
     current = obtainNext(current) 
    } while current != nil 
} 

kindaCStyleLoop(view, obtainNext: { $0.parent }) { 
    // Do stuff with $0 
} 

Ve for-in-döngü sözdizimi kullanarak etkinleştirmek için GeneratorType ve SequenceType dayanan bir sonuncuyu örneğin:

struct CStyleGenerator<T> : GeneratorType, SequenceType { 
    let getNext: T -> T? 
    var current: T! 

    init(first: T, getNext: T -> T?) { 
     self.getNext = getNext 
     self.current = first 
    } 

    mutating func next() -> T? { 
     defer { 
      if current != nil { 
       current = getNext(current) 
      } 
     } 
     return current 
    } 
} 

for parentView in CStyleGenerator(first: view, getNext: { $0.parent }) { 
    // Do stuff with parentView 
} 
+0

cevabını vermek için ayıklanırken İsteğe bağlı güvenli bir şekilde bir süre içinde sarılmış olabilir – pkacprzak

+1

Açık bir seçenek yerine örtülü bir isteğe bağlı kullanmak için cevabımı güncelledim. – Valentin

+0

Bu, parentView sonunda nil olduğunda çökecektir. Önceden olduğu gibi bırakabilir veya while döngüsünün içindeki isteğe bağlı paketi kapatabilirsiniz – pkacprzak

0

for view in views where view.superview != nil { 
} 
+0

"görünümler" nedir? – brigadir

1

Corr vb ama çok-Geç cevap: orada çözüm sağlamak Swift 3'te yerleşik işlevler şunlardır:

public func sequence<T>(first: T, next: (T) -> T?) -> UnfoldSequence<T, (T?, Bool)> 
public func sequence<T, State>(state: State, next: (inout State) -> T?) -> UnfoldSequence<T, State> 

Biz bu şekilde onları kullanabilirsiniz: gerçekten

sequence(first: view, next: { 
    // do something with $0... 
    return $0.superview 
}) 
+0

Kullanmıyorsanız, içeri girmek zorunda değilsiniz. Sadece dizi fonksiyonunu kullanın. – Binarian

+1

true! düzeltme için teşekkürler – brigadir