7

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

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

然后我得到错误:

无法使用类型为“(的:(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 
    } 
}
4

1 回答 1

6

这几乎可以肯定只是协议(又名存在主义)不符合自身这一事实的延伸。因此,存在类 UIViewController & MyDelegate不符合Equatable,即使符合UIViewController

因此,因为index(of:)被限制在Collection带有Equatable元素的 a 上调​​用,所以不能在 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)
}

我们不能将fas 作为参数传递给foo(_:)as Foo & Xdoesn't conform to P,即使Foo确实如此。然而,实际上这应该是一个明确的案例,即存在主义应该始终能够符合自己,所以我继续提交了一个 bug

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

foo(f as Foo)

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

let index = (self.viewControllers as [UIViewController]).index(of: myController) 
于 2017-06-11T21:22:33.683 回答