2010-12-29 20 views
8

NSInvocation nesnesine bir nil argümanını nasıl (veya hatta) gönderebilirim? NSInvocation nil argümanı

Bunu yapmaya çalıştım:

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]; 

bu mesajla kilitlenmesine ilk yaklaşım:

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 

İkinci yaklaşım bu mesajla kilitlenmesine:

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

Teşekkür herhangi bir yardım için önceden!

cevap

9

Evet, geçersiz argümanları geçebilirsiniz. Daha doğrusu, içeriği nil olan geçerli bir işaretçi iletebilirsiniz.

Sorununuzu yeniden oluşturamadım. İşte test ettiğim kod. Programınızda hataya neden olan başka bir şey olabilir. Bu senin hatayı tetikleyebilecek görüneni beri

#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; 
} 

Ben de NSInvocationOperation kullanarak ve doğrudan -retainArguments göndermeden test ettik. [: AtIndex: NSInvocation setArgument] Geçerli bir bellek adresi kopyalanır bir tampon işaret beklediğini - beri Kayıt için

, ikinci yaklaşım çalışmaz. Nesne argümanlarında, tampon nesnenin adresini içermelidir. Nesnenin adresi sıfır olabilir, ancak arabellek adresi geçerli olmalıdır.

+0

Haklısınız. Sorunun, argümanların sıfır değerleriyle ayarlanması/ayarlanması ile ilgisi yoktur. Benim olmayan argümanlarımdan biri çifte ilkel bir dizilimdir ve onu, ikincisini nesneye aktarmadan önce çift bir işaretçiye dönüştürmeyi unutmuşum. –

3

Bunu, sıfır olarak kalmak istediğiniz argüman dizini için setArgument:atIndex: numaralı telefonu aramamadan yapabilirsiniz. Bununla birlikte, eğer bu argümanı sıfırdan başka bir şeye ayarlamışsanız ve onu tekrar sıfırlamak isterseniz, birkaç hızlı test yapamayacağınızı gösteriyor gibi görünüyor. Yanlış olabilirdim, ama yeni bir çağırma nesnesi oluşturmanız ve tüm istenen değerleri el ile kopyalamanız, nil olarak kalmak istediğiniz argümanı çıkarmanız gerektiği gibi görünüyor.

+0

Haklısınız. Ben nil args için 'setArgument: atIndex:' demeyi düşünmediğimi ve gerçekten denediğimi söylemeyi unuttum. Sorun hiç benim argümanımla ilgili değildi. –