2010-01-25 9 views
6

Escribo código Objective-C y con frecuencia me he dado cuenta de que tengo que usar una variable de clase para almacenar un valor para usar una vez. Después de consumirlo ya no lo necesito. Para mí, almacenar este valor en una variable de clase parece ser un olor a código. Realmente el valor debe pasarse como un parámetro a los métodos que estoy usando.¿Cómo se eliminan las variables de clase de uso único del código Objective-C?

Me encuentro con esto por lo general cuando estoy consumiendo delegados. Como ejemplo, tengo una IU con múltiples botones utilizados para cargar y mostrar un UIActionSheet cuando se tocan. Esta hoja de acción contiene un selector de fecha que establece un valor para UILabel cuando se descarta la hoja de acción.

- (IBAction)setPurchaseDateTapped { 
    self.activeField = purchaseDate; 
    [self loadDatePickerActionSheet:@"Edit Purchase Date"]; 
} 

- (void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex { 
    self.activeField.text = value_from_UIActionSheet; 
} 

Como se puede ver aquí, la devolución de llamada actionSheet clickedButtonAtIndex no me permite pasar el activeField por lo que tienen que utilizar una variable de clase. Parece más correcto escribir esto:

- (void)actionSheet:(UIActionSheet *)actionSheet parameterValue:(id)parameter { 
    parameter.text = value_from_UIActionSheet; 
} 

Creo que puedo subclase el delegado UIActionSheet y UIActionSheet y añadir las firmas que requiero, pero de nuevo esto parece más esfuerzo que vale la pena (?).

Así que mi pregunta es ¿cuál es la mejor manera de hacer lo que estoy tratando de hacer?

No necesariamente quiero cambiar la interfaz del selector de fecha/hoja de acción que he creado (aunque si hay un mejor patrón para configurar múltiples fechas en un UIView mientras mantiene DatePicker fuera del camino, me ' . m todo oídos)

Respuesta

3

En este caso, creo que un simple subclase de UIActionSheet sería el camino a seguir:

@interface SpecialActionSheet : UIActionSheet 
{ 
    id parameter; 
} 
@property (assign) id parameter; 
@end 

@implementation SpecialActionSheet 
@synthesize parameter; 
@end 

esto debería ser suficiente, ya que todo lo que quiere hacer es tener la actionSheet mantener un parámetro. Ahora, el código podría ser como sigue:

- (void)loadDatePickerActionSheet:(NSString *)caption forField:(UITextField *)field { 
    //... 
    datePickerActionSheet.parameter = field; 
} 

- (IBAction)setPurchaseDateTapped { 
    [self loadDatePickerActionSheet:@"Edit Purchase Date" forField:purchaseDate]; 
} 

- (void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex { 
    UITextField * field = ((SpecialActionSheet *)actionSheet).parameter; 
    field.text = value_from_UIActionSheet; 
} 
2

Mi enfoque habitual en estas situaciones es usar la propiedad etiqueta en UIAlertViews, y hacer un interruptor en el mismo (que es un número entero). No es tan bueno como tener una cuerda o algo para pasar, pero si tienes múltiples alertas, es una forma fácil de desambiguar. Por ejemplo:

... 
actionSheet.tag = [fields indexOfObject: self.activeField]; 
...  //fields is an NSArray of all the field objects I might have on the screen 


- (void)actionSheet:(UIActionSheet *)actionSheet parameterValue:(id)parameter { 
    [[field objectAtIndex: actionSheet.tag] setText: value_from_UIActionSheet]; 
} 
+0

No tenía conocimiento de la propiedad de etiquetas. Tendré que investigar esto. –

2

Otra solución es use associative storage.

UIActionSheet ya disponga de ella. Puede probarlo por

[myActionSheet setValue:@"test value" forKey:@"testKey]; 
NSLog(@"%@",[myActionSheet valueForKey:@"testKey]; 

El almacenamiento asociativo es bastante ingenioso si no se usa en exceso.

Cuestiones relacionadas