2010-11-02 15 views
72

Me gustaría almacenar bloques Object-c en una propiedad para su uso posterior. No estaba seguro de cómo hacerlo, así que busqué en Google un poco y hay muy poca información sobre el tema. Pero al final he logrado encontrar la solución y he pensado que valdría la pena compartirla con otros novatos como yo.Cómo almacenar bloques en propiedades en Objective-C?

Inicialmente pensé que necesitaría escribir las propiedades a mano para usar Block_copy & Block_release.

Afortunadamente he descubierto que blocks are NSObjects y - copy/- release es equivalente a Block_copy/Block_release. Entonces puedo usar @property (copy) para auto generar setters & getters.

+1

duplicado posible de [? ¿Puedo utilizar Objective C-bloques como propiedades] (http://stackoverflow.com/questions/3935574/can-i-use-objective-c-blocks-as-properties) Esta pregunta es más reciente que la de allí. –

+1

Código de ejemplo completo, ACTUALIZADO, explicado simplemente para principiantes: http://stackoverflow.com/a/20760583/294884 – Fattie

+1

Para los nuevos lectores, esta pregunta extremadamente antigua ahora es felizmente extremadamente pasada de moda. Usted simplemente dice ** @ property (copy) void (^ doStuff) (void); ** con nada más o menos que copiar. nowadys esto se explica con claridad de cristal (incluido el por qué) en una serie de lugares en el Apple doco. no podría ser más simple; esa es toda la respuesta. De hecho, todo el tema tiene un valor histórico, ya que ahora solo usa Swift. – Fattie

Respuesta

130

Editar: actualizado para ARC

typedef void(^MyCustomBlock)(void); 

@interface MyClass : NSObject 

@property (nonatomic, copy) MyCustomBlock customBlock; 

@end 

@implementation MyClass 

@end 

MyClass * c = [[MyClass alloc] init]; 
c.customBlock = ^{ 
    NSLog(@"hello....."); 
} 

c.customBlock(); 
+4

¿Alguien sabe por qué para los bloques debe usar (no atómico, copiar) y no (no atómico, retener)? Normalmente se usa retener y no puedo encontrar ningún lugar que explique por qué usar copy for blocks. –

+0

@StevePotter realmente? Encontré un par de preguntas relevantes aquí en SO en cuestión de segundos. Por ejemplo: http://stackoverflow.com/a/4667422/115730 y los comentarios a http://stackoverflow.com/a/3935677/115730 –

+27

Sí Dave, de verdad. Puedo buscar también y también vi esos. Las explicaciones fueron vagas, como si usara la copia "para que realmente sobrevivan al marco de pila". Pensé que retener el objeto también lo haría. Ninguno explicó cómo se asignan los bloques a la pila. Sin embargo, un comentario se vinculó a un artículo - http://cocoawithlove.com/2009/10/how-blocks-are-implemented-and.html que lo explicó bien. Consulte en "Los bloques son objetos un poco extraños". ¡Así que gracias! –

95

Otra posibilidad, sin typedef

@property (copy, nonatomic) void (^selectionHandler) (NSDictionary*) ;

+16

Para aclarar, como la sintaxis es tan opaca, esta es una propiedad de bloque llamada "selectionHandler" que toma un argumento NSDictionary * y devuelve el vacío. –

+0

No creo que sea tan difícil de leer, pero estoy de acuerdo en que se ve mejor con typedef. Tiendo a escribir un montón de typedefs para los parámetros que normalmente quiero aprobar: PFObjectBlock, PFStringBlock, PFArrayBlock, PFErrorBlock, etc. – Besi

+0

¿id, SEL, IMP permitirían más simplificaciones? – dklt

9

puede encontrar una muy buena explicación de esto en la WWDC 2012 de sesión 712 que comienza en la página 83 La forma correcta de guardar un bloque en ARC es la siguiente:

@property(strong) my_block_type work; 

Tenga cuidado con los ciclos de retención. Una buena manera de resolver se establece el bloque a cero cuando no lo necesita más:

self.work = nil; 
+2

solo con ARC. Bajo MRC esto está mal. Pero 'copy' funciona correctamente bajo MRC y ARC – newacct

+0

No creo que la copia funcione bien en todos los casos en MRC, pero tal vez en la mayoría de ellos –

+0

' copy' es precisamente la forma correcta de hacerlo en MRC. – newacct

Cuestiones relacionadas