Why does NSInvocation getReturnValue: lose object? - objective-c

I need your help. I have some problems with NSInvocation 'getReturnValue:' method. I want to create UIButton programmatically, and even more, I want to create it dynamically using NSInvocation and through passing value through the NSArray (that's why I wrapped UIButtonTypeRoundedRect).
Listing.
NSLog(#"Button 4 pushed\n");//this code executed when button pushed
Class cls = NSClassFromString(#"UIButton");//if exists {define class},else cls=nil
SEL msel = #selector(buttonWithType:);
//id pushButton5 = [cls performSelector:msel withObject:UIButtonTypeRoundedRect];//this code works correctly,but I want to do this by NSInvocation
//---------------------------
NSMethodSignature *msignatureTMP;
NSInvocation *anInvocationTMP;
msignatureTMP = [cls methodSignatureForSelector:msel];
anInvocationTMP = [NSInvocation invocationWithMethodSignature:msignatureTMP];
[anInvocationTMP setTarget:cls];
[anInvocationTMP setSelector:msel];
UIButtonType uibt_ = UIButtonTypeRoundedRect;
NSNumber *uibt = [NSNumber numberWithUnsignedInt:uibt_];
NSArray *paramsTMP;
paramsTMP= [NSArray arrayWithObjects:uibt,nil];
id currentValTMP = [paramsTMP objectAtIndex:0];//getParam from NSArray
NSInteger i=2;
void* bufferTMP;
//if kind of NSValue unwrapp it.
if ([currentValTMP isKindOfClass:[NSValue class]]) {
NSUInteger bufferSize = 0;
NSGetSizeAndAlignment([currentValTMP objCType], &bufferSize, NULL);
bufferTMP = malloc(bufferSize);
[currentValTMP getValue:bufferTMP];//copy currentVal to bufer
[anInvocationTMP setArgument:bufferTMP atIndex:i];// The +2 represents the (self) and (cmd) offsets
}else {
[anInvocationTMP setArgument:&currentValTMP atIndex:i];//Again,+2 represents (self) and (cmd) offsets
}
void* result = malloc([[cls methodSignatureForSelector:msel] methodReturnLength]);
[anInvocationTMP invoke];
[anInvocationTMP getReturnValue:result];
NSLog(#"sizeof(UIButton)=%i,sizeof(result)=%i,methodreturnlength = %i,sizeof(*result)=%i",class_getInstanceSize(NSClassFromString(#"UIButton")),sizeof(result),[[cls methodSignatureForSelector:msel] methodReturnLength],sizeof(*result));
id pushButton5;
pushButton5=result;
//---------------------------
NSLog output: sizeof(UIButton)=140,sizeof(result)=4,methodreturnlength = 4,sizeof(*result)=1
The problem is that value from NSInvocation is pointer of size 4 bytes. It should point to UIButton object,size of 140 bytes. But actually refers to 1 byte data. So what does happen with UIButton object,that should be initialized by 'buttonWithType:'?
Added after getting some answers:
To clarify: I want to get UIButton object, but after this code id pushButton5 = (id) result; ,when I try to work with pushButton5,it causes EXC_BAD_ACCESS. Can someone help me?
Can this happen because of this?
Class cls = NSClassFromString(#"UIButton");
...
[anInvocationTMP setTarget:cls];
It is correct, isn't it?

If you're using ARC, I would replace this:
void* result = malloc([[cls methodSignatureForSelector:msel] methodReturnLength]);
[anInvocationTMP invoke];
[anInvocationTMP getReturnValue:result];
With this:
CFTypeRef result;
[anInvocationTMP invoke];
[anInvocationTMP getReturnValue:&result];
if (result)
CFRetain(result);
UIButton *pushButton5 = (__bridge_transfer UIButton *)result;
The reason is that the invokation's return object is not retained, so it will go away, even if you immediately assign it to an object reference, unless you first retain it and then tell ARC to transfer ownership.

result has type void* and your sizeof(*result) expression is measuing sizeof(void), which apparently yields 1 in your compiler.
To check type of an Objective-C object, use isKindOfClass: method:
id resObj = (id)result;
if ([resObj isKindOfClass:[UIButton class]])
NSLog(#"mazel tov, it's a button");
Just be sure it's really an objective-c object first.

The return value is a UIButton* not a UIButton. Thus everything looks fine in your code.

It's not a problem.
First, getReturnValue: should come after the invocation. So,
[anInvocationTMP getReturnValue:result];
[anInvocationTMP invoke];
should be
[anInvocationTMP invoke];
[anInvocationTMP getReturnValue:result];
Next, you should forget about the size of UIButton itself. What buttonWithType returns is UIButton*, not UIButton. In Objective-C, you should never directly deal with the object itself. You should always work with a pointer to the object.
Finally, (Objective-)C's sizeof operator is purely compile-time operation. So, sizeof(*result) doesn't know at all what result points to at the run time. But it doesn't matter... you shouldn't care about the size of UIButton, as I already told you.

Really answer that I needed was... How do you think where ? Yes, in documentation.
Use the NSMethodSignature method methodReturnLength to determine the size needed for buffer :
NSUInteger length = [[myInvocation methodSignature] methodReturnLength];
buffer = (void *)malloc(length);
[invocation getReturnValue:buffer];
When the return value is an object, pass a pointer to the variable (or memory) into which the object should be placed :
id anObject;
NSArray *anArray;
[invocation1 getReturnValue:&anObject];
[invocation2 getReturnValue:&anArray];
So the problem solved. Thanks for your respond guys.

Related

Objective C - Passing a float through a selector

I'm trying to pass a float through a selector using 'withObject:' however, it only accepts objects.
There are solutions that tell me to use [NSNumber numberWithFloat: ] however it's messing with the value of my float. I am doing a before and after testing of the values of the float, and beforehand I get numbers such as 0.0034324, whereas afterwards they are all 0.0000000
[[self gameObjects] makeObjectsPerformSelector:#selector(update:) withObject: <what to put here>]];
Thanks in advance!
EDIT*
here is the context
-(void) tick:(float)dt{
NSLog(#"%f",dt)
[[self gameObjects] makeObjectsPerformSelector:#selector(update:) withObject:[NSNumber numberWithFloat:dt]];
}
The number outputted from above is NOT 0
But from the selector method....
- (void)update:(float)dt{
NSLog(#"%f",dt);
}
The output is 0
You should wrap the float in an NSNumber.
NSNumber * num = [NSNumber numberWithFloat:5.5];
EDIT:
As rmaddy has pointed out, here are some other ways to use NSNumber *
NSNumber * num = #5.5f;
float someFloat = 5.5f;
NSNumber * num1 = #(someFloat);
To OP,
We need to see more of your code to help dissect the actual problem
Update to respond to new context
In your target method you are specifying that you expect a (float) as the expected argument. It is important to be cognizant of the type of variable you are passing to functions. Notice the last argument to your makeObjectsPerformSelector method is prefaced as withObject. This indicates you are passing an object, not a primitive float. So wrap the float you want to pass in an NSNumber as such:
NSNumber * numToPass = #(floatToWrap);
[[self gameObjects] makeObjectsPerformSelector:#selector(update:) withObject:numToPass]];
- (void)update:(NSNumber *)dt {
NSLog(#"%f",dt.floatValue); // or [dt floatValue];
}
Hope this helps
As stated by others, you've made some mistake in your attempt to use NSNumbers and would probably be better off asking us to look at that code.
I ran the following:
float value = 0.0034324f;
NSNumber *valueObject = #(value);
NSLog(#"%0.7f, %#", value, valueObject);
Output was:
2013-07-12 17:45:07.948 Untitled[4950:707] 0.0034324, 0.0034324
The issue was that I didn't change my selected method to accomodate an NSNumber, as it still had a float as its parameter type.
Thanks for the help everybody.
[[self gameObjects] makeObjectsPerformSelector:#selector(update:) withObject:[NSNumber numberWithFloat:dt]];
Calls a selector that has a float argument.
Chang the update: argument to NSNumber and inside it call floatValue on the NSNumber
Probably better to just do a for-in loop on your array of gameObjects than all this performSelector and NSNumber business. In the loop call the update netheid directly.
You are looking for NSInvocation. It's not the most pleasant thing to write, but it does exactly what you asked for:
- (void)update:(CGFloat)value
{
XCTAssertEqualsWithAccuracy(value, 2.1, 0.001, #"");
}
- (void)testNSInvocationOverArrayWithFloatArgument
{
CGFloat value = 2.1;
NSArray *gameObjects = #[ self ];
for (id object in gameObjects) {
NSMethodSignature *signature = [object methodSignatureForSelector:#selector(update:)];
NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:signature];
[invocation setTarget:object];
[invocation setSelector:#selector(update:)];
[invocation setArgument:&value atIndex:2];
[invocation invoke];
}
}

objective C using a string to call a method

Hi im new to objective C and was wondering if someone might be able to help me with this. I have a few different methods each requiring 3 input values and normally call it using
[self methodA:1 height:10 speed:3]
but the method name I want to read from a string in a plist so for example if the string was methodB i would get
[self methodB:1 height:10 speed:3]
for "methodC"
[self methodC:1 height:10 speed:3]
and so on.
Any ideas how I might do this I tried defining the string as a Selector using NSSelectorFromString
NSString *string = [plistA objectForKey:#"method"];
SEL select = NSSelectorFromString(string);
[self performSelector:select:c height:b speed:a];
However this did not work either any help would be greatly appreciated.
Have tried the solution below but could not get to work here is what i've tried.
So just to recap I have methods such as
spawnEnemyA:2 withHeight:3 withSpeed:4
spawnEnemyB:3 withHeight:2 withSpeed:5
and I want to read the values I want to pass to these methods as well as the method type from a plist file. my code is as follows, //////////////////////////////////////////////////////////////
//These are the values I read from the plist that I want my method to use
int a = [[enemySettings objectForKey:#"speed"] intValue];
int b = [[enemySettings objectForKey:#"position"] intValue];
int c = [[enemySettings objectForKey:#"delay"] intValue];
// I Also read the method name from the plist and combine it into a single string
NSString *method = [enemySettings objectForKey:#"enemytype"];
NSString *label1 = #"spawn";
NSString *label2 = #":withHeight:withSpeed:";
NSString *combined = [NSString stringWithFormat:#"%#%#%#",label1, method,label2];
//Check that the string is correct get spawnEnemyA:withHeight:withSpeed:
CCLOG(#"%#",combined);
//This is the Invocation part
NSInvocation * invocation = [ NSInvocation new ];
[ invocation setSelector: NSSelectorFromString(combined)];
[ invocation setArgument: &c atIndex: 2 ];
[ invocation setArgument: &b atIndex: 3 ];
[ invocation setArgument: &a atIndex: 4 ];
[ invocation invokeWithTarget:self ];
[invocation release ];
////////////////////////////////////////////////////////////////////
The code compiles without any errors but the methods are not called. Any ideas? Cheers
You can't use performSelector for a method with 3 (or more) arguments.
But for your information, here's how to use it:
SEL m1;
SEL m2;
SEL m3;
m1 = NSSelectorFromString( #"someMethodWithoutArg" );
m2 = NSSelectorFromString( #"someMethodWithAnArg:" );
m1 = NSSelectorFromString( #"someMethodWithAnArg:andAnotherOne:" );
[ someObject performSelector: m1 ];
[ someObject performSelector: m2 withObject: anArg ];
[ someObject performSelector: m2 withObject: anArg withObject: anOtherArg ];
For methods with more than 2 arguments, you will have to use the NSInvocation class.
Take a look at the documentation to learn how to use it.
Basically:
NSInvocation * invocation = [ NSInvocation new ];
[ invocation setSelector: NSStringFromSelector( #"methodWithArg1:arg2:arg3:" ) ];
// Argument 1 is at index 2, as there is self and _cmd before
[ invocation setArgument: &arg1 atIndex: 2 ];
[ invocation setArgument: &arg2 atIndex: 3 ];
[ invocation setArgument: &arg3 atIndex: 4 ];
[ invocation invokeWithTarget: targetObject ];
// If you need to get the return value
[ invocation getReturnValue: &someVar ];
[ invocation release ];
In general, this kind of dynamism often indicates an anti-pattern. Colluding data with implementation in this fashion is not generally a best practice.
Sometimes, though, it is necessary. If you are going down this path, then given that your various method declarations likely look like:
- (void)methodAWidth:(NSUInteger)w height:(NSUInteger)h speed:(NSUInteger)s;
- (void)methodBWidth:(NSUInteger)w height:(NSUInteger)h speed:(NSUInteger)s;
- (void)methodCWidth:(NSUInteger)w height:(NSUInteger)h speed:(NSUInteger)s;
You would probably want something like:
NSString *selName = [NSString stringWithFormat:#"method%#Width:height:speed:", ... one of #"A", #"B", or #"C" ....];
SEL selector = NSelectorFromString(selName);
Then:
if (![target respondsToSelector:selector])
return; // no can do
void (*castMsgSend)(id, SEL, NSUInteger, NSUInteger, NSUInteger) = (void*)objc_msgSend;
castMsgSend(target, selector, 1, 10, 3);
Every method call is compiled down to a call to objc_msgSend(). By doing the above, you are creating a fully type-safe/type-checked call site that goes through the normal Objective-C messaging mechanism, but the selector is dynamically defined on the fly.\
While performSelector: (and multi-arg variants) are handy, they can't deal with non-object types.
And, as MacMade pointed out in a comment, watch out for floating point and structure returns. They use different variants of objc_msgSend() that the compiler automatically handles in the normal [foo bar] case.
You can directly use objc_msgsend:
NSString *methodName = [plistA objectForKey:#"method"];
objc_msgSend(self, methodName, c, b, a);
Mind that the selector must include all pieces, eg #"method:height:speed:"
You should replace the following line with:
[self performSelector:select:c height:b speed:a];
and write following:
[self performSelector:select withObject:[NSArray arrayWithObjects:c,b,a,nil]];

How to allow NSMutableDictionary to accept 'nil' values?

I have this statement:
[custData setObject: [rs stringForColumnIndex:2] forKey: #"email"];
where [rs stringForColumnIndex:2] obtained from a SQLite3 d/b has a value of nil. The app crashes giving me the error:
NSCFDictionary setObject:forKey:]: attempt to insert nil value (key: email)'
Is there a way to prevent this? (like a setting for NSMutableDictionary?)
UPDATE: this is what I finally did:
[custData setObject: ([rs stringForColumnIndex:2] != nil? [rs stringForColumnIndex:2]:#"") forKey: #"email"];
There is a non-nil object called NSNull that is built specifically to represent nils in situations where "plain" nil is not acceptable. If you replace your nils with [NSNull null] object, NSDictionary will take them. You would need to check for NSNull on the way out, though.
Note that this is important only when you must differentiate between a value not being set and a value being set to nil. If your code is such that it can interpret a missing value as nil, you do not need to use NSNull at all.
It is not possible with a pure NSMutableDictionary, and in most cases you want to convert nil values into [NSNull null] or just omit them from the dictionary. Sometimes (very seldom), though, it is convenient to allow nil values, and in those cases you can use CFMutableDictionary with custom callbacks.
If you go this way, I recommend that you use CoreFoundation API for all accesses, e.g. CFDictionarySetValue and CFDictionaryGetValue.
However, if you know what you're doing, you can use toll-free bridging and cast that CFMutableDictionary to NSMutableDictionary or NSDictionary. This may be useful if you have a bunch of helpers that accept NSDictionary, and you want to use them on your modified nil-capable dictionary. (Of course, make sure that the helpers aren't surprised by nil values.)
If you do the bridging, note that:
1) NSMutableDictionary setter raises errors on nil values before bridging, so you need to use CFDictionarySetValue to set values that are potentially nil.
2) technically, we're violating a contract of NSMutableDictionary here, and things may break (e.g. in future OS updates)
3) a lot of code will be very surprised to find nil values in a dictionary; you should only pass the bridged frankendictionaries to the code that you control
See ridiculousfish's post on toll-free bridging for an explanation of why a bridged CFDictionary behaves differently from NSDictionary.
Example:
#import <Foundation/Foundation.h>
const void *NullSafeRetain(CFAllocatorRef allocator, const void *value) {
return value ? CFRetain(value) : NULL;
}
void NullSafeRelease(CFAllocatorRef allocator, const void *value) {
if (value)
CFRelease(value);
}
const CFDictionaryValueCallBacks kDictionaryValueCallBacksAllowingNULL = {
.version = 0,
.retain = NullSafeRetain,
.release = NullSafeRelease,
.copyDescription = CFCopyDescription,
.equal = CFEqual,
};
int main(int argc, const char * argv[])
{
#autoreleasepool {
CFMutableDictionaryRef cfdictionary = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kDictionaryValueCallBacksAllowingNULL);
CFDictionarySetValue(cfdictionary, #"foo", #"bar");
CFDictionarySetValue(cfdictionary, #"boz", nil);
NSMutableDictionary *dictionary = CFBridgingRelease(cfdictionary);
NSLog(#"dictionary[foo] = %#", dictionary[#"foo"]);
NSLog(#"dictionary[foo] = %#", dictionary[[#"fo" stringByAppendingString:#"o"]]);
NSLog(#"dictionary[boz] = %#", dictionary[#"boz"]);
NSLog(#"dictionary = %#", dictionary);
NSLog(#"(dictionary isEqualTo: dictionary) = %d", [dictionary isEqualToDictionary:dictionary]);
}
return 0;
}
outputs:
dictionary[foo] = bar
dictionary[foo] = bar
dictionary[boz] = (null)
dictionary = {
boz = (null);
foo = bar;
}
(dictionary isEqualTo: dictionary) = 1
I needed to set a NSDictionary value to one that may or may not be set yet from NSUserDefaults.
What I did was wrap the values in a stringwithFormat call. Both values are not yet set so start as null. When I run without the stringwithFormat call the app crashes. So I did this and in my situation worked.
-(NSDictionary*)userDetailsDict{
NSDictionary* userDetails = #{
#"userLine":[NSString stringWithFormat:#"%#",[[NSUserDefaults standardUserDefaults]stringForKey:kSelectedLine] ],
#"userDepot":[NSString stringWithFormat:#"%#",[[NSUserDefaults standardUserDefaults]stringForKey:#"kSelected Duty Book"]]
};
return userDetails;
}

#selector - With Multiple Arguments?

I have been using #selector today for the first time and have not been able to work out how to do the following? How would you write the #selector if you had more than one argument?
No arguments:
-(void)printText {
NSLog(#"Fish");
}
[self performSelector:#selector(printText) withObject:nil afterDelay:0.25];
Single argument:
-(void)printText:(NSString *)myText {
NSLog(#"Text = %#", myText);
}
[self performSelector:#selector(printText:) withObject:#"Cake" afterDelay:0.25];
Two arguments:
-(void)printText:(NSString *)myText andMore:(NSString *)extraText {
NSLog(#"Text = %# and %#", myText, extraText);
}
[self performSelector:#selector(printText:andMore:) withObject:#"Cake" withObject:#"Chips"];
Multiple Arguments: (i.e. more than 2)
NSInvocation
- (id)performSelector:(SEL)aSelector
withObject:(id)anObject
withObject:(id)anotherObject
From the Documentation:
This method is the same as performSelector: except that you can supply two arguments for aSelector. aSelector should identify a method that can take two arguments of type id. For methods with other argument types and return values, use NSInvocation.
so in your case you would use:
[self performSelector:#selector(printText:andMore:)
withObject:#"Cake"
withObject:#"More Cake"]
As an alternative for NSInvocation when you have more than two parameters, you can use NSObject's -methodForSelector: as in the following example:
SEL a_selector = ...
Type1 obj1 = ...
Type2 obj2 = ...
Type3 obj3 = ...
typedef void (*MethodType)(id, SEL, Type1, Type2, Type3);
MethodType methodToCall;
methodToCall = (MethodType)[target methodForSelector:a_selector];
methodToCall(target, a_selector, obj1, obj_of_type2, obj_of_type3);
I had an issue where I needed to use the afterDelay along with multiple arguments to my #selector method. Solution? Use a wrapper function!
Say this is the function I want to pass to #selector:
-(void)myFunct:(NSString *)arg1 andArg:(NSString *)arg2 andYetAnotherArg:(NSString *)arg3;
Obviously, I can't even use withObject: withObject: here, so, make a wrapper!
-(void)myFunctWrapper:(NSArray *)myArgs {
[self myFunct:[myArgs objectAtIndex:0] andArg:[myArgs objectAtIndex:1] andYetAnotherArg:[myArgs objectAtIndex:2]];
}
and use it by doing:
NSArray *argArray = [NSArray arrayWithObjects:string1,string2,string3,nil];
[self performSelector:#selector(myFunctWrapper:) withObject:argArray afterDelay:1.0];
This way I can have multiple arguments and use the selector with delay.
#selector(printText:andMore:)
[self performSelector:#selector(printText:andMore) withObject:#"Cake" withObject:#"More Cake"];
Another option is to use an even shorter syntax:
#import <objc/message.h> // objc_msgSend
...
((void (*)(id, SEL, Type1, Type2, Type3))objc_msgSend)(target, a_selector, obj1, obj_of_type2, obj_of_type3);
Elaborating on Ben-Uri's answer, which can be written way shorter.
E.g. calling the UIView method - (CGPoint)convertPoint:(CGPoint)point toView:(UIView *)view can
be done as follows:
SEL selector = #selector(covertPoint:toView:);
IMP method = [viewA methodForSelector:selector];
CGPoint pointInB = method(viewA, selector, pointInA, viewB);
As KennyTM pointed out, the selector syntax is
#selector(printText:andMore:)
You call it with
performSelector:withObject:withObject.
... if you need more arguments or different types, you need to use NSIvocation
Using NSInvocation as you specify you can create an NSObject category that implements
- (void)performSelector:(SEL)aSelector withObjects:(NSArray *)arguments;
Something like:
- (void)performSelector:(SEL)aSelector withObjects:(NSArray *)arguments
{
NSMethodSignature *signature = [self methodSignatureForSelector: aSelector];
NSInvocation *invocation = [NSInvocation invocationWithMethodSignature: signature];
[invocation setSelector: aSelector];
int index = 2; //
for (NSObject *argument in arguments) {
[invocation setArgument: &argument atIndex: index];
index ++;
}
[invocation invokeWithTarget: self];
}
from: iOS - How to implement a performSelector with multiple arguments and with afterDelay?

Unrecognised selector yet debug can see it

I have a class that contains a collection of objects. I am trying to create a method that will return the first member of the collection matching a supplied predicate.
Here is the collection method:
...
//predicate is a boolean method that accepts an object as its single parameter
-(id<Notation>) getFirstChildMatching: (SEL) predicate declaredInInstance:(id) instance
{
NSMethodSignature *sig = [[instance class] instanceMethodSignatureForSelector:predicate];
NSInvocation *myInvocation = [NSInvocation invocationWithMethodSignature:sig];
[myInvocation setTarget:instance];
[myInvocation setSelector:predicate];
int numItems = childNotations.count;
for(int i=0;i< numItems;i++)
{
id<Notation> thisNotation = [childNotations objectAtIndex:i];
[myInvocation setArgument:thisNotation atIndex:2];
BOOL result =NO;
[myInvocation retainArguments];
[myInvocation invoke];
[myInvocation getReturnValue:&result];
if (result)
return thisNotation;
}
return nil;
}
I have created a test class that tests this method.
Here is the test method plus the predicate:
- (void) testGetFirstChildMatching
{
Leaf *line1 = [[Leaf alloc] initWithValue:1 step:Step_A andNumber:1];
Leaf *line2 = [[Leaf alloc] initWithValue:2 step:Step_B andNumber:2];
SEL mySelector = #selector(valueIs1:);
id<CompositeNotation> compositeNotation = [[CompositeNotation alloc] init];
[compositeNotation addNotation:line1];
[compositeNotation addNotation:line2];
id notation = [compositeNotation getFirstChildMatching: mySelector declaredInInstance:self];
STAssertEquals(YES, [notation isKindOfClass:[Leaf class]], #"Should be of type Leaf: %#", notation);
//Leaf *found = ((Leaf *)notation);
STAssertEquals([notation value], line1.value, #"Should have found line 1 with value 1: actual %i", [notation value]);
[line1 release];
[line2 release];
}
-(BOOL) valueIs1: (Leaf *) leaf
{
if (leaf.value == 1)
return YES;
return NO;
}
What I am finding is that on the "if (leaf.value == 1)" line I am getting an "unrecognized selector sent to class". What doesn't make sense is that the debugger can see the value property and it's value so the object clearly has that select.
Any ideas?
btw Leaf implements the notation protocol
Typo in function definition?
-(BOOL) valueIs1: (Leaf *) Leaf // <== should be "leaf" not "Leaf" ?
The fact that you're getting an "unrecognized selector sent to class", not instance, implies that leaf is a Class. Two things to check:
Ensure that Leaf's initializer initWithValue is returning an object.
Ensure that addNotation: is correctly adding Leafs to the array.
I eventually found the problem.
It was this line
[myInvocation setArgument:thisNotation atIndex:2];
it should have been
[myInvocation setArgument:&thisNotation atIndex:2];
Thanks