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
Post a Comment