如何将UIViewControllers数组转换为协议类型数组

时间:2015-05-04 09:13:53

标签: ios cocoa swift cocoa-touch foundation

我有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()
    }
}

3 个答案:

答案 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()
}