Swift 3: 如何写这个 for(;;) 循环
Swift 3: how to write this for(;;) loop
看起来 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: { [=13=].parent }) {
// Do stuff with [=13=]
}
最后一个依赖 GeneratorType
和 SequenceType
来启用 for-in-loop 语法:
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: { [=14=].parent }) {
// Do stuff with parentView
}
比如
for view in views where view.superview != nil {
}
正确但为时已晚的答案:Swift 3 中的内置函数提供了解决方案:
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>
我们可以这样使用它们:
sequence(first: view, next: {
// do something with [=11=]...
return [=11=].superview
})
看起来 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: { [=13=].parent }) {
// Do stuff with [=13=]
}
最后一个依赖 GeneratorType
和 SequenceType
来启用 for-in-loop 语法:
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: { [=14=].parent }) {
// Do stuff with parentView
}
比如
for view in views where view.superview != nil {
}
正确但为时已晚的答案:Swift 3 中的内置函数提供了解决方案:
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>
我们可以这样使用它们:
sequence(first: view, next: {
// do something with [=11=]...
return [=11=].superview
})