2015-01-05 26 views
3

我使用的扩展与像类方法的现有类尝试:如何在带有泛型的Swift扩展中使用带可选类方法的协议?

@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说:“命令/应用程序/ Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/swiftc失败,退出代码1”。如果我在协议中不使用“可选”,我不需要在扩展中解开foo(),即使删除“self”,一切都可以正常工作。任何人都可以告诉我为什么以及如何使可选工作正确吗? 在此先感谢。

回答

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强制转换,因为如果您试图直接拨打p上的.dynamicType.foo?(),您将获得“访问协议类型值'MyProtocol.Type'的成员未实现”。如果通用版本的崩溃与此相关,我不会感到惊讶。

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

+0

关于此的实际代码要复杂得多。这是我如何优化与路由器一起使用Alamofire的设计。可以不使用可选的(只是一些额外的行),但问题真的让我困惑。谢谢你的解释! – Wizard

相关问题