1

I am trying to create a new instance of my custom class (custom init method call, with a BOOL parameter) dynamically. How can I use NSInvocation to do that?

This is what I have so far:

NSMethodSignature* signature = [NSClassFromString(className) instanceMethodSignatureForSelector: sel];
NSInvocation* invocation = [NSInvocation invocationWithMethodSignature: signature];
[invocation setTarget: [NSClassFromString(className) alloc]];
[invocation setSelector:sel];
[invocation setArgument:&value atIndex:2];
[invocation invoke];
[invocation getReturnValue:&obj];

Above sample throws error in line [invocation invoke]; error is "message sent to deallocated instance".

Wain
  • 118,658
  • 15
  • 128
  • 151
user516542
  • 107
  • 2
  • 8
  • Are you declaring the `value` and `obj` parameters that are being used for return values? – Abizern Mar 21 '14 at 15:17
  • Yes, I have declared them. – user516542 Mar 21 '14 at 15:18
  • Any particular reason you need to use NSInvocation? Would `[[NSClassFromString(className) alloc] init]` work for you? Or perhaps if your classes share the same custom init method: `[[NSClassFromString(className) alloc] initWithValue:value]` – BergQuester Mar 21 '14 at 15:18
  • Where are you adding them? – Abizern Mar 21 '14 at 15:18
  • I have custom init which takes boolean. I need to dynamically create instance by calling the init that actually takes boolean. perform selector would nt help as it takes Object, whereas bool is not an object. – user516542 Mar 21 '14 at 15:19
  • 1
    Why? Why are you not using a superclass or a protocol to specify the generic interface and then using that to create the instance? – Wain Mar 21 '14 at 15:22
  • What do you mean to dynamically create instance? Why not just do a direct call, or delayed call via block? What are you trying to do? – hamstergene Mar 21 '14 at 15:22
  • NSObject *obj; BOOL value=YES; This is how i am declaring both variables above the code snip given above – user516542 Mar 21 '14 at 15:23
  • @Wain I want an reusable implementation, which can create instance for any class(name will be an argument to use this implementation). performselector would help if we have init objects. But in case if I have BOOL that needs to be passed for init-call, then performselector wouldn't help, hence i have gone for NSInvocation. – user516542 Mar 21 '14 at 15:30
  • @user516542 Why not do `Class cls = NSClassFromString(className); id instance = [[cls alloc] initWithBool:value];`? – hamstergene Mar 21 '14 at 15:37
  • @user516542 If you make `NSZombieEnabled=YES` you will easily detect which object is the actual problem here. It is very possible the problem is inside `init...` method, because your code as it is seems fine: unless some of involved objects are already deallocated, it should work well. – hamstergene Mar 22 '14 at 00:21

1 Answers1

4

Your code doesn't work because the NSInvocation doesn't retain the target or any arguments unless you tell it to (with retainArguments). So, you alloc an instance and then it gets destroyed before you invoke the NSInvocation.

Alternatively, create an instance variable and store the alloc'd instance there, then pass that to the NSInvocation.

Wain
  • 118,658
  • 15
  • 128
  • 151