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

android - InAppBilling registering BroadcastReceiver in AndroidManifest -

python Tkinter Capturing keyboard events save as one single string -

sql server - Why does Linq-to-SQL add unnecessary COUNT()? -