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

Joh*_*ese 7 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}
Run Code Online (Sandbox Code Playgroud)

然后我得到错误:

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

如何解决这个问题,是否有比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 
    } 
}
Run Code Online (Sandbox Code Playgroud)

Ham*_*ish 6

这几乎肯定只是协议(又称存在)不符合自身这一事实的延伸.所以阶级存在主义 UIViewController & MyDelegate并不符合Equatable,即使UIViewController这样.

因此,因为index(of:)被限制为Collection使用Equatable元素调用,所以不能在a上调用它[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)
}
Run Code Online (Sandbox Code Playgroud)

我们能不能通过f作为参数来foo(_:)作为Foo & X不符合P,即使Foo做.然而,这应该是一个明确的案例,表明存在主应该始终能够与自己相符,所以我继续提出了一个错误.

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

foo(f as Foo)
Run Code Online (Sandbox Code Playgroud)

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

let index = (self.viewControllers as [UIViewController]).index(of: myController) 
Run Code Online (Sandbox Code Playgroud)