3

我正在尝试使用具有类方法的现有类的扩展,例如:

@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 failed with exit code 1”。如果我不在协议中使用“可选”,我不需要在扩展中解开 foo() 并且即使我删除了“self”,一切都会正常工作。谁能告诉我为什么以及如何使可选功能正常工作?提前致谢。

4

1 回答 1

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'的成员未实现”。如果通用版本的崩溃与此有关,我不会感到惊讶。

我还要说,值得问自己是否真的需要带有可选方法(尤其是类级别的方法)的协议,以及是否有一种方法可以使用泛型完全静态地做你想做的事情(因为你已经在半做) .

于 2015-01-05T18:10:52.750 回答