I am trying using extension for an existing class with class method like:
@objc public protocol MyProtocol {
optional class func foo() -> Int
}
And I am using this protocol in an extension with generic like:
extension MyClass {
public func bar<T: MyProtocol>() {
...
let x: Int = T.self.foo!() // if I do not use "self" or "!" here, I will have a compiler error
...
}
This should work but when I build it, Xcode says "Command /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/swiftc failed with exit code 1". If I do not use "optional" in the protocol, I do not need to unwrap the foo() in the extension and everything works well even if I remove the "self". Can anyone tell me why and how to make the optional work properly? Thanks in advance.
It looks like you've found a (fairly obscure) bug in the Swift compiler that's causing it to crash.
Here's a reproduction that's all you need in a single file to crash swiftc
:
import Foundation
@objc protocol P { optional class func f() }
func f<T: P>(t: T) { T.self.f?() }
(you don't need to call f
for it to crash)
You should probably file a radar since the compiler crashing is never expected behavior no matter what your code.
If you tried to do this without the optional
, it'll work (and you can even ditch the self
). My guess is the implementation of generics doesn't currently account for the possibility of optional class-level functions.
You can do it without generics like this:
func f(p: MyProtocol) {
(p as AnyObject).dynamicType.foo?()
}
(there may even be a better way but I can't spot it).
You need the AnyObject
cast because if you try to call .dynamicType.foo?()
on p
directly you get "accessing members of protocol type value 'MyProtocol.Type' is unimplemented". I wouldn't be surprised if the crash of the generic version is related to this.
I'd also say that its worth asking yourself whether you really need a protocol with optional methods (especially class-level ones) and whether there's a way to do what you want entirely statically using generics (as you're already semi-doing).
来源:https://stackoverflow.com/questions/27779473/how-to-use-a-protocol-with-optional-class-methods-in-an-extension-with-generic-i