Apple は C ループを好まないようですが、それに対する適切なアプローチを提供していません (または見つけられませんでした)。UI階層のビューからルートに移動するループがあります:
for var parentView = view; parentView != nil; parentView = parentView.parent {
...
}
これをSwift 3の方法で書く方法は?
これはSwift 3でそれを行う方法です:
var parentView: View! = view
while parentView != nil {
// Do stuff
parentView = parentView.parent
}
while
ループの進行をブロックの最後ではなく隣にグループ化したい場合は、次のdefer
ように を使用できます。
var parentView: View! = view
while parentView != nil {
defer { parentView = parentView.parent }
// Do stuff
}
のスコープを制限したい場合はparentView
、すべてをdo
ブロックにカプセル化できます。
do {
var parentView: View! = view
while parentView != nil {
defer { parentView = parentView.parent }
// Do stuff
}
}
しかし、これは非常に冗長なので、次のように、同様のループに対して新しい汎用関数を定義できます。
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
}
そして、for-in-loop 構文を使用して有効にGeneratorType
する最後のもの:SequenceType
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
}
例えば
for view in views where view.superview != nil {
}