如果元素上的某些条件失败,那么继续循环是一种非常常见的习惯。
假设我们想对某种类型的所有子视图执行某些操作(并且出于某种原因,不希望对某些类型的东西进行处理)。理想情况下,我们会写:
for view in self.subviews as [NSView] { // cast required in beta 6
if (let specificView = view as? SpecificView) == nil { // <- Error here
continue
}
// Do things at a sensible indentation level
}
上面的代码失败,“模式变量绑定不能出现在表达式中”,如this question中所示。
但是,这似乎是一种常见模式, 是在Swift中实现它的一种方式。我错过了什么吗?
if let
语句的范围规则相悖,这些语句只将变量范围限定在内部块中。
考虑到这一点,我想稍微扩大一下这个问题:人们如何在Swift中应用 这种模式?
答案 0 :(得分:10)
这是一种有点常见的模式,但它不是良好的模式。我已经看到它向ObjC项目注入了错误。它假设视图层次结构过多,并且当变化时变得脆弱(例如当有人注入额外的视图时,你不期望为了管理旋转;真实的故事)。更好的模式是维护一个指向您要跟踪的SpecificView
(或视图)的属性。一般来说,向下倾斜是需要避免的,而不是优化的。
那就是说,这不是一种可怕的模式,有时它是一种非常有用的模式。那你怎么处理呢?
let specifics = self.subviews
.filter { $0 is SpecificView }
.map { $0 as SpecificView }
for view in specifics { ... }
这是一种常见的模式,所以也许我们可以对它进行泛化?
extension Array {
func filterByClass<T>(c: T.Type) -> [T] {
return self.filter { $0 is T }.map { $0 as T }
}
}
for view in self.subviews.filterByClass(SpecificView) { ... }
尽管如此,我认为应尽可能避免采用这种方法,而不是过度简化。