我正在尝试使用类方法的现有类的扩展名:
@objc public protocol MyProtocol {
optional class func foo() -> Int
}
我在扩展程序中使用此协议,如:
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
...
}
这应该可行但是当我构建它时,Xcode说“Command /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/swiftc失败,退出代码为1”。如果我不在协议中使用“可选”,我不需要在扩展中打开foo(),即使我删除了“self”,一切都运行良好。任何人都可以告诉我为什么以及如何使可选的工作正常? 提前谢谢。
答案 0 :(得分:2)
看起来你在Swift编译器中发现了一个(相当模糊的)错误导致它崩溃。
这是一个只需要在单个文件中崩溃swiftc
所需的复制品:
import Foundation
@objc protocol P { optional class func f() }
func f<T: P>(t: T) { T.self.f?() }
(您无需致电f
让它崩溃)
您应该提交雷达,因为无论您的代码是什么,编译器崩溃都不是预期的行为。
如果您尝试在没有optional
的情况下执行此操作,它将起作用(您甚至可以放弃self
)。我的猜测是泛型的实现目前没有考虑可选类级函数的可能性。
你可以在没有这样的泛型的情况下做到这一点:
func f(p: MyProtocol) {
(p as AnyObject).dynamicType.foo?()
}
(甚至可能有更好的方法,但我无法发现它。)
您需要AnyObject
强制转换,因为如果您尝试直接在.dynamicType.foo?()
上调用p
,则会“访问协议类型值'MyProtocol.Type'的成员未实现”。如果泛型版本的崩溃与此相关,我不会感到惊讶。
我还要说自己是否真的需要一个带有可选方法的协议(尤其是类级别的方法)以及是否有办法完全静态地使用泛型(因为你已经是半-doing)。