iphone ios selector performselector

iphone - iOS: ¿cómo implementar un performSelector con múltiples argumentos y con afterDelay?



(8)

Soy un novato de iOS. Tengo un método selector de la siguiente manera:

- (void) fooFirstInput:(NSString*) first secondInput:(NSString*) second { }

Estoy tratando de implementar algo como esto -

[self performSelector:@selector(fooFirstInput:secondInput:) withObject:@"first" withObject:@"second" afterDelay:15.0];

Pero eso me da un error diciendo -

Instance method -performSelector:withObject:withObject:afterDelay: not found

¿Alguna idea de lo que me estoy perdiendo?


Acabo de hacer algunos swizzling y necesitaba llamar al método original. Lo que hice fue hacer un protocolo y transmitirle mi objetivo. Otra forma es definir el método en una categoría, pero necesitaría la supresión de una advertencia (#pragma clang diagnostic ignored "-Wincomplete-implementation").


La opción más simple es modificar su método para tomar un único parámetro que contenga ambos argumentos, como un NSArray o NSDictionary (o agregar un segundo método que tome un solo parámetro, descomprimirlo, y llame al primer método, y luego llamar al segundo método en un retraso).

Por ejemplo, podrías tener algo como:

- (void) fooOneInput:(NSDictionary*) params { NSString* param1 = [params objectForKey:@"firstParam"]; NSString* param2 = [params objectForKey:@"secondParam"]; [self fooFirstInput:param1 secondInput:param2]; }

Y luego para llamarlo, puedes hacer:

[self performSelector:@selector(fooOneInput:) withObject:[NSDictionary dictionaryWithObjectsAndKeys: @"first", @"firstParam", @"second", @"secondParam", nil] afterDelay:15.0];


No me gusta el modo NSInvocation, demasiado complejo. Vamos a mantenerlo simple y limpio:

// Assume we have these variables id target, SEL aSelector, id parameter1, id parameter2; // Get the method IMP, method is a function pointer here. id (*method)(id, SEL, id, id) = (void *)[target methodForSelector:aSelector]; // IMP is just a C function, so we can call it directly. id returnValue = method(target, aSelector, parameter1, parameter2);


Personalmente, creo que una solución más cercana a sus necesidades es el uso de NSInvocation.

Algo como lo siguiente hará el trabajo:

indexPath y dataSource son dos variables de instancia definidas en el mismo método.

SEL aSelector = NSSelectorFromString(@"dropDownSelectedRow:withDataSource:"); if([dropDownDelegate respondsToSelector:aSelector]) { NSInvocation *inv = [NSInvocation invocationWithMethodSignature:[dropDownDelegate methodSignatureForSelector:aSelector]]; [inv setSelector:aSelector]; [inv setTarget:dropDownDelegate]; [inv setArgument:&(indexPath) atIndex:2]; //arguments 0 and 1 are self and _cmd respectively, automatically set by NSInvocation [inv setArgument:&(dataSource) atIndex:3]; //arguments 0 and 1 are self and _cmd respectively, automatically set by NSInvocation [inv invoke]; }


Porque no existe un [NSObject performSelector:withObject:withObject:afterDelay:] .

Necesita encapsular los datos que desea enviar en un solo objeto Objective C (por ejemplo, un NSArray, un NSDictionary, algún tipo personalizado de Objective C) y luego pasarlo a través del [NSObject performSelector:withObject:afterDelay:] que está bien conocido y amado

Por ejemplo:

NSArray * arrayOfThingsIWantToPassAlong = [NSArray arrayWithObjects: @"first", @"second", nil]; [self performSelector:@selector(fooFirstInput:) withObject:arrayOfThingsIWantToPassAlong afterDelay:15.0];


Puede empaquetar sus parámetros en un objeto y usar un método de ayuda para llamar a su método original como Michael, y otros ahora, han sugerido.

Otra opción es dispatch_after, que tomará un bloque y lo enrutará en un momento determinado.

double delayInSeconds = 15.0; dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, delayInSeconds * NSEC_PER_SEC); dispatch_after(popTime, dispatch_get_main_queue(), ^(void){ [self fooFirstInput:first secondInput:second]; });

O, como ya ha descubierto, si no necesita el retraso, puede usar - performSelector:withObject:withObject:


Puede encontrar todos los tipos de métodos ofrecidos por Selector: aquí:

http://developer.apple.com/library/mac/#documentation/Cocoa/Reference/Foundation/Classes/nsobject_Class/Reference/Reference.html

Hay un montón de variaciones, pero no hay una versión que tome varios objetos, así como un retraso. En su lugar, deberá finalizar sus argumentos en un NSArray o NSDictionary.

- performSelector: - performSelector:withObject: - performSelector:withObject:withObject: – performSelector:withObject:afterDelay: – performSelector:withObject:afterDelay:inModes: – performSelectorOnMainThread:withObject:waitUntilDone: – performSelectorOnMainThread:withObject:waitUntilDone:modes: – performSelector:onThread:withObject:waitUntilDone: – performSelector:onThread:withObject:waitUntilDone:modes: – performSelectorInBackground:withObject:


- (void) callFooWithArray: (NSArray *) inputArray { [self fooFirstInput: [inputArray objectAtIndex:0] secondInput: [inputArray objectAtIndex:1]]; } - (void) fooFirstInput:(NSString*) first secondInput:(NSString*) second { }

y llámalo con:

[self performSelector:@selector(callFooWithArray) withObject:[NSArray arrayWithObjects:@"first", @"second", nil] afterDelay:15.0];