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 nil
s). 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