Swift 4无法调用'索引'使用类型的参数列表

时间:2017-06-11 14:55:44

标签: arrays swift swift4

我在调用数组方法index(of:)时遇到问题。 MyClass继承自UIViewController并符合MyDelegate协议。

//self.viewControllers: [(UIViewController & MyDelegate)]
guard let myController = viewController as? MyClass,
let index = self.viewControllers.index(of: myController) else {return}

然后我收到错误:

  

无法调用'索引'使用类型'(of:(UIViewController& MyDelegate))的参数列表'

如何解决此问题并提供比在扩展程序中实施index(of:)更好的解决方案?

extension Array where Element == (UIViewController & MyDelegate) { 
    func index(of: Element) -> Int? { 
        for i in 0..<self.count { 
            if self[i] == of {
                return i
            } 
        } 
        return nil 
    } 
}

1 个答案:

答案 0 :(得分:6)

这几乎可以肯定只是协议(又名存在)don't conform to themselves这一事实的延伸。因此class existential UIViewController & MyDelegate不符合Equatable,即使UIViewController也是如此。

因此,由于index(of:)仅限于使用Collection元素在Equatable上调用,因此您无法在[UIViewController & MyDelegate]上调用它。

这是一个更小的例子:

protocol P {}
protocol X {}
class Foo : P {}

func foo<T : P>(_ t: T) {}

func bar(_ f: Foo & X) {
  // error: Protocol type 'Foo & X' cannot conform to 'P' because only concrete
  // types can conform to protocols
  foo(f)
}

我们无法将f作为参数传递给foo(_:),因为Foo & X不符合P,即使Foo也是如此。然而,这应该是一个明确的案例,表明存在主义的应该始终能够与自己相符合,所以我继续filed a bug

在修复之前,一个简单的解决方案就是对混凝土类型进行中间强制转换 - 所以在我们的示例中,我们可以这样做:

foo(f as Foo)

在您的示例中,您可以执行以下操作:

let index = (self.viewControllers as [UIViewController]).index(of: myController)