Swift closure in array becomes nil in Objective-c

前端 未结 2 483
死守一世寂寞
死守一世寂寞 2020-12-21 10:14

I created an objective-c method which will invoke a method via NSInvocation:

typedef void (^ScriptingEmptyBlock)();
typedef void (^ScriptingErrorBlock)(NSErr         


        
2条回答
  •  感动是毒
    2020-12-21 10:38

    success is not nil (in fact, NSArray cannot contain nils). If you print it like NSLog(@"%@", success);, it will say (Function), not (null). And if you print its class like NSLog(@"%@", [success class]);, it will say _SwiftValue. Basically, it is a Swift value that is bridged into Objective-C.

    The problem is that the object success points to is not an Objective-C block. It is a Swift closure, and Swift closures are not the same as Objective-C blocks. Trying to use invoke it as if it were an Objective-C block causes undefined behavior. po in the debugger prints it wrong probably because it is printing it assuming it were type ScriptingEmptyBlock (a block type). If you do po (id) success, it will print (Function).

    As to how you can explicitly put an Objective-C block into the array from Swift, the only way I figured out to do it something like:

    let params:[Any] = [ "testName",
                         successClosure as (@convention(block) () -> Void)!,
                         errorClosure as (@convention(block) (NSError) -> Void)!]
    object.scripting_execute (ScriptOperation.updateProductName.rawValue,
                              withParams: params)
    

    I am not sure why it's necessary to put the function type inside a !, but it doesn't seem to work otherwise. Maybe someone else can find a better way.

提交回复
热议问题