Hay cuatro maneras de hacer una devolución de llamada:
puntero de función Usted puede hacer un puntero de función si realmente quiere, pero no es recomendable. Se hace de la misma manera que lo haría en C. El problema es que no puede usar un puntero a un método Objective-C. Se ve algo como esto:
void callback(/* Some args */) {
// Some callback.
}
- (void)doSomethingAndCallThisFunctionWhenDone:(void(*)(/* Some args */))func {
// Do something.
if (func)
func(/* Some args */);
}
- (void)start {
[self doSomethingAndCallThisFunctionWhenDone:&callback];
}
selectores Puede utilizar -performSelector :. Se ve así:
- (void)doSomethingAndCallTarget:(id)target withSelector:(SEL)sel {
// Do something.
[target performSelector:sel];
}
- (void)start {
SomeOtherObject * someOtherObject = [[SomeOtherObject alloc] init];
[self doSomethingAndCallTarget:someOtherObject withSelector:@selector(MyCallback)];
}
delegados uso de un delegado. Esto es similar a UITableViewDelegate/UITableViewDataSource. Vea el Apple docs here. Es posible hacerlo de esta manera:
- (void)doSomethingDelegate:(id<MyCallbackObject>)delegate {
[delegate retain];
// Do something.
[delegate performMyCallback]; // -performMyCallback must be declared in the MyCallbackObject protocol and implemented by SomeOtherObject.
[delegate release];
}
- (void)start {
id<MyCallbackObject> someOtherObject = [[SomeOtherObject alloc] init];
[self doSomethingDelegate:someOtherObject];
[someOtherObject release];
}
Bloques La forma preferida para las devoluciones de llamada es el uso de bloques. Solo están disponibles para iOS 4.0+ o Mac OS X 10.6+. Se ve algo como esto:
- (void)doSomethingAndCallThisBlockWhenDone:(void(^)(/* Some args */))block {
[block copy];
// Do something.
if (block)
block(/* Some args */);
[block release];
}
- (void)start {
[self doSomethingAndCallThisBlockWhenDone:^void(/* Some args */){ // Return type and arguments may be omitted if you don't have any.
// Your callback
}];
}
Como se puede ver con el bloque, es más fácil de leer y su devolución de llamada está en línea con su código. Esto es especialmente bueno para que no tenga que cazarlo. Hay muchos más beneficios de bloques, pero posiblemente no podría cubrirlos a todos aquí.
Una última cosa, si usa un bloque, querrá usar un typedef
para que no tenga que escribir tipos de bloques oscuros como void(^)(/* Some args */)
todo el tiempo. El typedef
podría tener este aspecto:
typdef void(^MyCallback)(/* Some args */);
A continuación, se puede declarar su método como este:
- (void)doSomethingAndCallThisBlockWhenDone:(MyCallback)block;
Actualización:
he mostrado más detalles de cómo implementar los diferentes técnicas (ver arriba).
Pero, ¿cuál es el lado del SomeOtherObject de esto? ¿Qué debe declararse en SomeOtherObject y qué necesita hacer? Tiene que tener un doSomethingAndCallThisFunctionWhenUrDone. Pero, ¿qué tiene que hacer para llamar a dicho método para el objeto ThisObject? Por cierto, un millón hasta ahora. – Joe
Expandí mi respuesta para mostrar algunos detalles más de implementación. Para los punteros y bloques de función no necesita un objeto para llamarlos, pero puede pasar objetos como argumentos. – rbrown