Me preguntaba si es posible almacenar una referencia a una función anónima (bloque) como una variable de instancia en Objective-C.

Sé cómo utilizar la delegación, el objetivo de la acción, etc. Yo no estoy hablando de esto.

InformationsquelleAutor Jacob Relkin | 2010-07-12

2 Comentarios

  1. 86

    Seguro.

    typedef void(^MyCustomBlockType)(void);
    
    @interface MyCustomObject {
      MyCustomBlockType block;
    }
    @property (nonatomic, copy) MyCustomBlockType block; //note: this has to be copy, not retain
    - (void) executeBlock;
    @end
    
    @implementation MyCustomObject
    @synthesize block;
    
    - (void) executeBlock {
      if (block != nil) {
        block();
      }
    }
    
    - (void) dealloc {
      [block release];
      [super dealloc];
    }
    @end
    
    //elsewhere:
    
    MyCustomObject * object = [[MyCustomObject alloc] init];
    [object setBlock:^{
      NSLog(@"hello, world!");
    }];
    
    [object executeBlock];
    [object release];
    • es allí una manera de tener un tipo genérico para un bloque? Odio que tengo que tener un typedef allí.
    • sí, usted puede hacer: void(^)(void) (o lo que sea de bloque de la firma que usted necesita) en cualquier lugar donde veas MyCustomBlockType. Sin embargo, yo promesa que el uso de la typedef, las cosas serán mucho más fáciles de asimilar en el largo plazo. Sin embargo, no hay manera de decir «cualquier bloque con cualquier valor de retorno y los parámetros. Debe ser explícito acerca de la firma.
    • Usted todavía está limitada por C del tipo de sistema. No hay tal cosa como un «genérico» del bloque, a pesar de que en C++ podría ser capaz de hacer algunas bastante la mente-flexión de las cosas con las plantillas y los bloques. De manera más realista, tipo id es genérico con respecto a Objective-C tipos, por lo que tomar y devolver (posiblemente cero) id‘s le da una gran flexibilidad.
    • ¿Por qué copiar, no fuerte? Incluso si estoy usando el ARCO?
    • 12 ’10 a las 16:46«, esto significa que la respuesta pre-fechas de ARCO 😉
    • ¿Por qué la liberación después de la llamada a executeBlock? Que solo quiero hacer que si usted estaba absolutamente seguro de que no se llamar de nuevo, ¿no? O es que llame necesario para la liberación de los capturados de las variables en la pila de bloque?
    • el punto fue para ilustrar cómo tener un bloque como ivar. La asignación, ejecución, y la liberación inmediata de un objeto de ayuda son sólo para proporcionar un contexto de cómo se puede utilizar este.
    • Gracias – ahora me doy cuenta de que yo creía, equivocadamente, que fueron la liberación de la cuadra a sí mismo como opuesto al objeto. Como de costumbre, he leído muy rápidamente.
    • Sólo para responder a la pregunta EXPLÍCITA preguntó a Jacob: @property (nonatomic, copia) vacío (^userObject)();

  2. 12

    Sí, usted seguramente puede almacenar una referencia a un (copia) de un Objetivo-C bloque. La declaración de la variable es un poco peludo, como C punteros a función, pero más allá de eso no hay problema. Para un bloque que lleva y id y devuelve void:

    typedef void (^MyActionBlockType)(id);
    
    @interface MyClass : NSObject 
    {
    
    }
    
    @property (readwrite,nonatomic,copy) MyActionBlockType myActionBlock;
    @end

    hará el truco.

    • La definición es, sin duda peludo. Yo por tanto prefieren usar typedef simplemente si. A continuación, puede hacer locuras «de los bloques que aceptar un bloque como parámetro y devuelve un bloque» y no perderse en el paréntesis. 🙂
    • Muy buen punto, Dave.
    • es este typedef void (^MyActionBlockType)(id); correcta? no debería ser typedef void (^MyActionBlockType)(id obj);
    • el nombre de la variable (obj) es irrelevante para el tipo, por lo tanto no es necesario declarar en typedef. El nombre sólo es relevante a la hora de implementar el bloque;

Dejar respuesta

Please enter your comment!
Please enter your name here