Search code examples
iosswifttyphoon

Swift - patch definition with selector using run-time arguments


I'm trying to create patcher for selector in assembly that uses run-time arguments feature but no luck. Has anyone solved similar issue or it can't be using Swift yet?

Method definition in assembly looks like this:

public dynamic func requestCodeApiGateway(phone: NSString) -> AnyObject {
    return TyphoonDefinition.withClass(RequestCodeApiGatewayImpl.self) { (definition) in
        definition.useInitializer("initWithApiService:apiRouter:phone:") { (initializer) in
            // ...
        }
    }
}

And I'm creating Patcher like this:

let patcher = TyphoonPatcher()
patcher.patchDefinitionWithSelector("requestCodeApiGatewayWithPhone:") { 
    // ...
}

P.S. solutions with partially using Objective-C would be also appreciated


Solution

  • It looks like you're using the wrong selector in patchDefinitionWithSelector. With the exception of init, initial parameters aren't exposed as external parameter names and aren't included in selectors.

    The selector for requestCodeApiGateway(NSString) is requestCodeApiGateway:.

    Updating your code to use that selector should do the trick:

    patcher.patchDefinitionWithSelector("requestCodeApiGateway:") { 
        // ...
    }
    

    Alternatively, you can get the selector to be requestCodeApiGatewayWithPhone: any of the following ways:

    1. Rename the method:

      public dynamic func requestCodeApiGatewayWithPhone(phone: NSString) -> AnyObject
      
    2. Expose the external parameter name using longhand or shorthand notation:

      public dynamic func requestCodeApiGateway(phone phone: NSString) -> AnyObject
      public dynamic func requestCodeApiGateway(#phone: NSString) -> AnyObject
      
    3. Override the selector registered with the Objective-C runtime:

      @objc(requestCodeApiGatewayWithPhone:)
      public dynamic func requestCodeApiGateway(phone: NSString) -> AnyObject
      

    Options 1 and 2 will affect any Swift code calling that method and all methods will have the same effect on Objective-C code and the Objective-C runtime.