2012-02-02 17 views
28

¿Es posible definir una propiedad de bloque Objective-C pero aún tener compleción de código completo en Xcode 4?Propiedad de bloque Objective-C con finalización de código Xcode

Si utilizo un typedef para definir el bloque:

typedef void (^CompletionBlock)(MyObject *myObj);

y luego definir la propiedad:

@property (nonatomic, copy) CompletionBlock completionBlock;

y luego @synthesize la propiedad no consigo código completo finalización al llamar al colocador. Xcode usará typedef y debido a esto, la finalización del código no utiliza la sintaxis completa del bloque completa con los parámetros del bloque, sino que utiliza el typedef.

Si defino un prototipo método en el encabezado que utiliza la sintaxis completa de bloque en lugar del typedef:

@property (nonatomic, copy) void (^completionBlock)(MyObject *myObj);

y luego utilizo @synthesize, el colocador siempre se acerca a la utilización de la finalización de código completa pero fundamentalmente la sintaxis que deja fuera los nombres de los parámetros:

[self setCompletionBlock:(void (^)(MyObject *)) { ... }

Por último, si trato de @synthesize y a continuación, sustituir la implementación incubadora o poner el prototipo en el encabezado:

- (void)setCompletionBlock:(void (^)(MyObject *myObj))completionBlock {...}

Una advertencia se eleva indica que el tipo de propiedad no coincide con el tipo de acceso. No importa cómo intente solucionar la sintaxis, no puedo definir una propiedad de bloque y un setter que tenga la sintaxis completa para completar el código. ¿Puedo tomar mi torta y comerla también?

Gracias!

+0

Nos recuerda la pregunta ... ¿por qué 'typedef' en absoluto? Para funcionalidad reducida y una línea de código semi redundante? Tal vez esta es la forma en que Apple dice ... ___ "¡No hagas eso!" ___ ?? –

Respuesta

32

Definitivamente puedes tener tu pastel y comértelo también, si estás dispuesto a agregar una línea adicional de código a la interfaz de tu clase.

En primer lugar, definir bloque con un typedef y crear una propiedad como lo hizo en su pregunta:

typedef void (^CompletionBlock)(MyObject *myObj); 

... 

@property (nonatomic, copy) CompletionBlock completionBlock; 

A continuación, como MobileOverload señaló en su respuesta, sabemos que Xcode ofrece completado de código correcto para typedef' d bloques si se usa en una declaración de método independiente. Por lo tanto, vamos a añadir una declaración explícita de la incubadora de completionBlock:

- (void)setCompletionBlock:(CompletionBlock)completionBlock; 

Cuando llama, este método resuelve con el método setter declarado por la propiedad. Sin embargo, como lo definimos explícitamente en la interfaz de clase, Xcode lo ve y aplica la finalización completa del código.

Por lo tanto, si incluye las tres líneas, debe obtener el resultado deseado. Este comportamiento es claramente una deficiencia de Xcode, ya que no hay ninguna razón por la cual un setter definido en una declaración @property deba tener una terminación de código diferente a la del mismo método definido por sí mismo. cosas

+2

Esto funciona, ¡gracias!Presentaré un informe de error para esto, así que con suerte no necesitaremos la declaración de método explícito en el futuro. – Andrew

+0

Si agrego la declaración explícita del colocador a mi archivo de interfaz, recibo una advertencia de proyecto que indica que tengo una implementación incompleta. Si declaro este setter en la interfaz, ¿debo implementarlo en .m? – djibouti33

+0

Debería obtener esa advertencia solo si no está declarando la propiedad o si el definidor que la propiedad define tiene una definición diferente a la que declaró explícitamente. – Matt

4

Puede obtener un acabado de código de aspecto elegante al pasar sus bloques como argumento para un método en su clase. En el archivo de cabecera que typedef'd el bloque como esto

typedef void (^MyCompletionBlock)(id obj1, id obj2); 

Entonces yo era capaz de utilizarlo como un argumento a mi método que también he declarado en esta cabecera de la clase.

-(void)doThisWithBlock:(MyCompletionBlock)block; 

En el archivo m I declaró el método

-(void)doThisWithBlock:(MyCompletionBlock)block { 
    NSLog(@"Something"); 
} 

y cuando fui a llamar a la misma Tengo la finalización de código de lujo como este. CodeCompletion1

CodeCompletion2

Esperamos que esto responda a su pregunta.

+2

Desafortunadamente, el comportamiento es diferente y Xcode no usa la sintaxis de bloque completo cuando define una '@ propiedad' con un tipo de bloque typedef y utiliza un método setter definido manualmente o un setter' @ sintetizado '' generado. – Andrew

+2

Me encontré con el mismo problema. A partir de Xcode 4.3.2 (4E2002) esto es correcto. Debe usar un typedef y una declaración de método explícita en su sección de interfaz. Ni usar una propiedad ni definir un método sin un bloque typedef'd es posible cuando se quiere completar el código completo. – Klaas

+0

TODAVÍA es así en Xcode (el número después de 4, edítame, si te atreves). UGH! –

0

No sé acerca de las terminaciones de código completo, pero puede usar fragmentos de código para obtener el comportamiento de finalización de código y puede usar marcadores de posición en fragmentos de código < #PLACE HOLDER #>. Espero que esto te ayude

1

Ok, así que encontró una manera provisional de hacer esto que does't como resultado advertencias/errores ... y haga a realidad más fácil de leer/escribir más corto, etc.

definen una macro con nuestra "abreviatura", y luego usar el formato completo en la declaración de bienes del mismo tipo ...

#define TINP NSString*(^)(NSString *typed, const char *raw) 
@interface .... 
@property (copy) NSString*(^termDidReadString)(NSString *typed, const char *raw); 

posteriormente .. se puede hacer referencia a ese "tipo" de la discusión, etc .. como

+ (void)addInputBlock:(TINP)termDidReadString; 

y voilá ... no solo su código será MÁS TANTO !! pero la finalización de código funcionará, como un encanto ...

enter image description here

Cuestiones relacionadas