ios - Swift closure in array becomes nil in Objective-c -


i created objective-c method invoke method via nsinvocation:

typedef void (^scriptingemptyblock)(); typedef void (^scriptingerrorblock)(nserror *error); - (void)scripting_execute:(nsstring *)operation withparams:(nullable nsarray *)args {      sel selector = [self scripting_selectorforoperation:operation];     class class = [self class];     nsmethodsignature *signature = [class instancemethodsignatureforselector:selector];     nsinvocation *invocation = [nsinvocation invocationwithmethodsignature:signature];      [invocation setselector:selector];     [invocation settarget:self];     (int idx = 0; idx < args.count; idx ++) {         id arg = args[idx];         [invocation setargument:&arg atindex:idx + 2];      }      scriptingemptyblock success = args[1];      // breakpoint added on next line test nil     success(); // nil , crash!     // (lldb) po args.count     // 3      // (lldb) po success     // printing description of success:     // (scriptingemptyblock) success = 0x0000000000000000      // (lldb) po args[1]     // (function)      //[invocation getargument:&success atindex:2]; // tried , got nil     [invocation invoke];  } 

the method takes "operation" translated selector overriding scripting_selectorforoperation: in subclasses , performs invocation.

all of works, except when invoked method has block arguments nil, added test nil describe comments, when attempting read closure array nil.

called like:

let successclosure: scriptingemptyblock = {                     print("renamed product")                 } let errorclosure: scriptingerrorblock = { error in                     print("failed rename product: \(error)")                 } let params:[any] = [ "testname", successclosure, errorclosure] object.scripting_execute (scriptoperation.updateproductname.rawvalue, withparams: params) 

why closure becoming nil?

success not nil (in fact, nsarray cannot contain nils). if print nslog(@"%@", success);, (function), not (null). , if print class nslog(@"%@", [success class]);, _swiftvalue. basically, swift value bridged objective-c.

the problem object success points not objective-c block. swift closure, , swift closures not same objective-c blocks. trying use invoke if objective-c block causes undefined behavior. po in debugger prints wrong because printing assuming type scriptingemptyblock (a block type). if po (id) success, print (function).

as how can explicitly put objective-c block array swift, way figured out like:

let params:[any] = [ "testname",                      successclosure (@convention(block) () -> void)!,                      errorclosure (@convention(block) (nserror) -> void)!] object.scripting_execute (scriptoperation.updateproductname.rawvalue,                           withparams: params) 

i not sure why it's necessary put function type inside !, doesn't seem work otherwise. maybe else can find better way.


Comments

Popular posts from this blog

python Tkinter Capturing keyboard events save as one single string -

android - InAppBilling registering BroadcastReceiver in AndroidManifest -

javascript - Z-index in d3.js -