2010-12-29 17 views
8

¿Cómo puedo (o puedo incluso) pasar un argumento nulo a un objeto NSInvocation?NSInvocación nil argumento

he tratado de hacer esto:

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

El primer enfoque se bloqueará con este mensaje:

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 

El segundo enfoque se bloqueará con este mensaje:

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

Gracias de antemano para cualquier ayuda!

Respuesta

9

Sí, puede pasar argumentos nulos. Más precisamente, puede pasar un puntero válido cuyos contenidos son nulos.

No he podido reproducir su problema en particular. Aquí está el código que he usado para probarlo. Probablemente hay algo más en su programa que está causando el error.

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

También hemos probado sin utilizar NSInvocationOperation y el envío de -retainArguments directamente, ya que eso es lo que parece estar provocando el error.

Para el registro, su segundo enfoque no funcionará, ya que - [NSInvocation setArgument: atIndex:] espera que una dirección de memoria válida apunte a un búfer que se copiará. En el caso de los argumentos del objeto, el buffer debe contener la dirección del objeto. La dirección del objeto puede ser cero, pero la dirección del búfer debe ser válida.

+0

Tienes razón. El problema no tiene nada que ver con establecer/no establecer los argumentos con valores nulos. Uno de mis argumentos no nulos es una matriz primitiva doble y olvidé convertirlo en un doble puntero antes de pasarlo al objeto de invocación. –

3

Puede lograr esto simplemente no llamando al setArgument:atIndex: para el índice del argumento que desea permanecer nulo.

Sin embargo, si ya ha establecido ese argumento en algo además de cero, y desea volver a cambiarlo a cero, algunas pruebas rápidas parecen indicar que simplemente no puede. Podría estar equivocado, pero parece que tendría que crear un nuevo objeto de invocación y copiar manualmente todos los valores deseados, menos el argumento que desea permanecer nulo.

+0

Tienes razón. Olvidé mencionar que pensé y en realidad lo intenté, simplemente no llamé a 'setArgument: atIndex:' para los nil args. El problema no estaba relacionado con mis argumentos nulos en absoluto. –

Cuestiones relacionadas