我有UITabBarController
viewControllers
全部实施协议Refreshable
。为什么我不能将标签栏控制器的viewControllers
属性解包到Refreshable
类型的数组中?
if let tabs = self.tabBarController.viewControllers as? [Refreshable] {
// Some code
tabs[0].refresh() // refresh() is a function in Refreshable
}
没有编译错误,但if let
闭包内的代码永远不会被执行。我怎么能正确地做到这一点?
ADD:
这很有效,但我不喜欢它 - 我觉得我应该像上面那样表达这一点。
if let tabs = self.tabBarController.viewControllers as? [UIViewController] {
if tabs[0] is Refreshable {
(tabs[0] as! Refreshable).refresh()
}
}
答案 0 :(得分:2)
标签栏控制器中的viewControllers
属性声明为[AnyObject]?
..因此类型检查as? [Refreshable]
不会通过。
相反,遍历视图控制器并检查每个控制器的类型:
for viewController in self.tabBarController!.viewControllers! {
if let refreshableTab = viewController as? Refreshable {
refreshableTab.refresh()
}
}
答案 1 :(得分:2)
如果您的数组是[UIViewController]
,则它不会接受类型为Refreshable
的项目,因为其他任意类可能符合它,但不具有{{1}的属性}}。
换句话说,仅UIViewController
对您的数组不具有足够的承诺,因为它不会保证Refreshable
个实例。
原始表达式只适用于数组,其中类型由协议类型指定,如下所示:
UIViewController
不幸的是,由于您在标签栏控制器上使用该属性,我担心这不适合您。确保仅使用符合// Suppose MyClass conforms to Refreshable
let myArray: [Refreshable] = [
MyClass(),
MyClass(),
MyClass(),
MyClass(),
]
// Now you can use refresh() without problems
for item in myArray {
item.refresh()
}
的实例的一种可能方法是首先过滤/映射数组,如下所示:
Refreshable
请务必注意,如果您使用let items = myarray.filter({ $0 is Refreshable }).map({ return $0 as! Refreshable })
// items will be [Refreshable]
for item in items {
item.refresh()
}
类型items
,则不能再认为它具有原始类的属性(即[Refreshable]
),只有协议授予它们的那些(在这种情况下是MyClass
)。
答案 2 :(得分:0)
结束@JózsefVesza很棒的回答,你可以做类似的事情:
if let tabs = self.tabBarController.viewControllers as? [UIViewController],
let refreshables = tabs.filter({ $0 is Refreshable }).map({ $0 as! Refreshable } {
refreshables[0].refresh()
}