简体   繁体   中英

Swift 4 Cannot invoke 'index' with an argument list of type

I have a problem with calling the array method index(of:) . MyClass inherits from UIViewController and conforms to the MyDelegate protocol.

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

then I get the error:

Cannot invoke 'index' with an argument list of type '(of: (UIViewController & MyDelegate))'

How can I solve this problem and is there a better solution than implementing index(of:) in an extension?

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 
    } 
}

This is almost certainly just an extension of the fact that protocols (aka. existentials) don't conform to themselves . So the class existential UIViewController & MyDelegate doesn't conform to Equatable , even though UIViewController does.

Therefore because index(of:) is constrained to being called on a Collection with Equatable elements, you cannot call it on a [UIViewController & MyDelegate] .

Here's a more minimal example:

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)
}

We cannot pass f as an argument to foo(_:) as Foo & X doesn't conform to P , even though Foo does. However really this should be a clear-cut case of where the existential should always be able to conform to itself, so I went ahead and filed a bug .

Until fixed, a simple solution is just to do an intermediate cast to the concrete type – so in our example, we can do:

foo(f as Foo)

and in your example, you can do:

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM