台风 - 如何注入符合PROTOCOL而不是CLASS的参数

时间:2014-11-28 14:43:51

标签: ios swift dependency-injection typhoon

我有代表记录用户的类

public class User: NSObject {        
    init(authenticator: Authenticator) {        
        self.authenticator = authenticator
    }
    ... 
}

它唯一的初始参数是符合 Authenticator协议

的对象
protocol Authenticator
{
    func authenticate(login:String , password:String , handler: (result:AuthenticationResult)->()  )
}

在我的例子中,Auth对象是类 BackendService

的实例

我的台风装配定义是:

public dynamic func user() -> AnyObject {
    return TyphoonDefinition.withClass(User.self) {
        (definition) in

        definition.useInitializer("initWithAuthenticator") {
            (initializer) in

            initializer.injectParameterWith( self.backendService() )
        }            
    }
}

应用程序原因运行时错误

'Method 'initWithAuthenticator' has 0 parameters, but 1 was injected. Do you mean 'initWithAuthenticator:'?'

如果我将init方法改为'initWithAuthenticator:',它会与

崩溃
'Method 'initWithAuthenticator:' not found on 'PersonalMessages.User'. Did you include the required ':' characters to signify arguments?'

1 个答案:

答案 0 :(得分:1)

目前,有必要添加' @ objc'指向Swift协议,使它们可用于Typhoon的依赖注入。没有它,Objective-c运行时的内省和动态调度功能是不可用的,这些都是必需的。

同样,对于一个类,它必须从NSObject扩展或者具有' @ objc'指令,否则它也将使用C ++样式vtable调度并且(基本上)没有反射。对于私人变量或方法,他们也必须拥有“动态”和“动态”。修改。

虽然vtable dispatch更快,但它可以防止运行时方法拦截,这是Cocoa最强大的功能,例如KVO所依赖的。因此,这两种范式都很重要,令人印象深刻的是Swift可以在它们之间切换。但就协议而言,使用' @ objc'指令有点不幸,因为它意味着一个传统的'行为。也许'动态'会更好吗?

dynamic protocol Authenticator //Not supported but would've been a nicer than '@objc'?
或许或许另一种暗示需要动态行为的方法是让协议扩展NSObject协议,但是这不起作用。所以使用' @ objc'是唯一的选择。

与此同时,对于课程而言,在使用Cocoa / Touch应用程序时,扩展NSObject的要求并不是真的难以理解。