2011-09-06 7 views
7

Esta es una extensión de este queston: Is it possible to create a category of the "Block" object in Objective-C.¿Puede ejecutarse un bloque Obj-C?

Básicamente, si bien parece posible crear una categoría en bloques, ya sea a través de NSObject o NSBlock, tengo problemas para entender cómo el bloque podría evaluarse a sí mismo. El ejemplo dado en la respuesta a la última pregunta:

- (void) doFoo { 
    //do something awesome with self, a block 
    //however, you can't do "self()". 
    //You'll have to cast it to a block-type variable and use that 
} 

implica que es posible colar algún modo auto a una variable de bloque, pero ¿cómo se ejecutará el bloque en sí? Por ejemplo, decir que hice una categoría en NSBlock y en un método hice:

NSBlock* selfAsBlock = (NSBlock*)self; 

¿Hay algún mensaje que puedo enviar a selfAsBlock tener el bloque de evaluar?

+0

Sí se puede. Puedes encontrar más en esto (ya en SO) http://stackoverflow.com/questions/4824613/is-there-a-self-pointer-for-blocks –

+0

No veo cómo eso resuelve este problema. Esa respuesta parece enfocarse en cómo llamar a un bloque desde su propia definición de bloque. Estoy hablando de evaluar un bloque desde el objeto de bloque en sí. Para ser un poco más específico, lo que espero lograr con esto es poder agregar métodos a los bloques (ya sea en NSObject o NSBlock) para hacer un flujo de control basado en bloques (es decir, [bloquear al mismo tiempo: Ejecutar bloque]). Para hacer esto, necesito que el bloque reevalúe en el método. – donalbain

Respuesta

7

implica que es posible colar algún modo auto a un bloque variable

De esta manera:

- (void)doFoo { 
    // Assume the block receives an int, returns an int, 
    // and cast self to the corresponding block type 
    int (^selfBlock)(int) = (int (^)(int))self; 

    // Call itself and print the return value 
    printf("in doFoo: %d\n", selfBlock(42)); 
} 

Tenga en cuenta que (en la mayoría de los casos) que debe arreglar la firma bloque para que el compilador puede configurar el sitio de llamada de acuerdo con la plataforma de destino ABI. En el ejemplo anterior, la firma es tipo de retorno int, parámetro único del tipo int.

Un ejemplo completo es:

#import <Foundation/Foundation.h> 
#import <objc/runtime.h> 

@interface Foo : NSObject 
- (void)doFoo; 
@end 

@implementation Foo 
- (void)doFoo { 
    // Assume the block receives an int, returns an int, 
    // and cast self to the corresponding block type 
    int (^selfBlock)(int) = (int (^)(int))self; 

    // Call itself and print the return value 
    printf("in doFoo: %d\n", selfBlock(42)); 
} 
@end 

int main(void) { 
    [NSAutoreleasePool new]; 

    // From Dave's answer 
    Method m = class_getInstanceMethod([Foo class], @selector(doFoo)); 
    IMP doFoo = method_getImplementation(m); 
    const char *type = method_getTypeEncoding(m); 
    Class nsblock = NSClassFromString(@"NSBlock"); 
    class_addMethod(nsblock, @selector(doFoo), doFoo, type); 

    // A block that receives an int, returns an int 
    int (^doubler)(int) = ^int(int someNumber){ return someNumber + someNumber; }; 

    // Call the category method which in turn calls itself (the block) 
    [doubler doFoo]; 

    return 0; 
} 
+0

Genial. Sin embargo, ¿es necesario agregar el código dinámico del método de ejecución? ¿O también se puede hacer a través de una categoría? – donalbain

+1

@don Como se explica en las respuestas a la pregunta que ha vinculado, no creo que sea posible utilizar una categoría, ya que el compilador necesita la declaración de la interfaz original al analizar una categoría. –

4

tiene un invoke método que se puede utilizar para llamar al bloque.

NSBlock* b = ^() { /* do stuff */ }; 
[b invoke]; 

Tenga en cuenta que este es un método privado, no documentado.

+1

Ese es el tipo de método que estaba buscando. Por supuesto, creo que todo lo que hago aquí es peligroso ya que NSBlock es privado y podría cambiar. – donalbain

+0

Si desea invocar el bloque simplemente puede hacer este bloque(); en lugar de [invocar bloque]; https://stackoverflow.com/a/9484268 – unmircea

Cuestiones relacionadas