2010-12-29 10 views
8

NSInvocationオブジェクトにnil引数を渡すにはどうすればよいですか(またはできますか)。NSInvocation nil引き数

私はこれを実行しようとしました:

NSMethodSignature* signature = [AClass instanceMethodSignatureForSelector:@selector(aMethod:theOtherArg:)]; 
NSInvocation* invocation = [NSInvocation invocationWithMethodSignature: signature]; 

[invocation setTarget: aTargetObj]; 
[invocation setSelector: @selector(aMethod:theOtherArg:)]; 

/* I've tried both this way */ 
AnObj* arg1 = nil; 
AnotherObj* arg2 = nil; 
[invocation setArgument: &arg1 atIndex:2]; 
[invocation setArgument: &arg2 atIndex:3]; 

/* and this way */ 
//[invocation setArgument: nil atIndex:2]; 
//[invocation setArgument: nil atIndex:3]; 

NSInvocationOperation* operation = [[NSInvocationOperation alloc] initWithInvocation:invocation]; 
//opQueue is an NSOperationQueue object 
[opQueue addOperation:operation]; 

最初のアプローチは、このメッセージでクラッシュします:

Thread 0 Crashed: 
0 libSystem.B.dylib    0x927c1f10 strlen + 16 
1 com.apple.CoreFoundation  0x92dd1654 __NSI3 + 500 
2 com.apple.CoreFoundation  0x92dd1994 -[NSInvocation retainArguments] + 132 
3 com.apple.Foundation   0x96a50c5e -[NSInvocationOperation initWithInvocation:] + 78 

第二のアプローチは、このメッセージでクラッシュします:

Error: Exiting due to caught object *** -[NSInvocation setArgument:atIndex:]: NULL address argument 

感謝助けを求めて事前に!

答えて

9

はい、nil引数を渡すことができます。より正確には、内容がnilである有効なポインタを渡すことができます。

私はあなたの特定の問題を再現できませんでした。ここでは私がそれをテストするために使用したコードです。あなたのプログラムにはおそらくエラーの原因となっているものがあります。

#import <Foundation/Foundation.h> 

@interface Person : NSObject { 
    NSString *name; 
    NSUInteger age; 
} 
- (void)setName:(NSString *)personName age:(NSNumber *)personAge; 
@end 

@implementation Person 
- (void)setName:(NSString *)personName age:(NSNumber *)personAge { 
    NSLog(@"setName:%@ age:%@", personName, personAge); 
    name = [personName copy]; 
    age = [personAge unsignedIntegerValue]; 
} 
@end 

int main() { 
    NSAutoreleasePool *pool = [NSAutoreleasePool new];    
    Person *person = [Person new]; 

    SEL sel = @selector(setName:age:); 

    NSMethodSignature *sig = [Person instanceMethodSignatureForSelector:sel]; 
    NSInvocation *inv = [NSInvocation invocationWithMethodSignature:sig]; 

    [inv setTarget:person]; 
    [inv setSelector:sel]; 

    NSString *name = nil; 
    NSNumber *age = nil; 

    [inv setArgument:&name atIndex:2]; 
    [inv setArgument:&age atIndex:3]; 

    // [inv retainArguments]; 
    // [inv invoke]; 

    NSInvocationOperation *op = [[[NSInvocationOperation alloc] initWithInvocation:inv] autorelease]; 
    NSOperationQueue *queue = [NSOperationQueue new]; 
    [queue addOperation:op]; 

    [pool release]; 
    return 0; 
} 

私はNSInvocationOperationを使用して、それがあなたのエラーをトリガしているようだ何だから、直接-retainArgumentsを送信せずに、それをもテストしてみました。

レコードの場合、 - [NSInvocation setArgument:atIndex:]は、コピーされるバッファを指す有効なメモリアドレスを必要とするため、2番目の方法は機能しません。オブジェクト引数の場合、バッファにはオブジェクトのアドレスが含まれていなければなりません。オブジェクトのアドレスはゼロにすることができますが、バッファのアドレスは有効でなければなりません。

+0

あなたは正しいです。この問題は、nil値で引数を設定する/しないこととは関係ありません。私のnon-nil引数の1つはdoubleプリミティブ配列で、呼び出しオブジェクトに渡す前にdoubleポインタにキャストするのを忘れていました。 –

3

これを達成するには、引数インデックスとしてをコールしないでください。

しかし、すでにその引数をnil以外の値に設定していて、それをnilに戻したい場合、いくつかの簡単なテストではできないことがわかります。私は間違っている可能性がありますが、新しい呼び出しオブジェクトを作成し、必要なすべての値を手動でnilに残したい引数を除いて手動でコピーする必要があるようです。

+0

あなたは正しいです。私は、実際には、 'setArgument:atIndex:'をnil argsと呼ぶのではなく、実際に試したことを忘れていました。問題は私の無関心な議論には全く関係していませんでした。 –