2010-01-25 16 views
6

J'écris du code Objective-C et j'ai fréquemment rencontré la situation où je dois utiliser une variable de classe pour stocker une valeur pour une utilisation unique. Après l'avoir consommé, je n'en ai plus besoin. Pour moi, stocker cette valeur dans une variable de classe ressemble à l'odeur du code. Vraiment, la valeur devrait être transmise en tant que paramètre aux méthodes que j'utilise. Je rencontre cette habitude quand je consomme des délégués. À titre d'exemple, j'ai une interface utilisateur avec plusieurs boutons utilisés pour charger et afficher un UIActionSheet quand ils sont engagés. Cette feuille d'action contient un sélecteur de date qui définit une valeur pour UILabel lorsque la feuille d'action est fermée. Comme vous pouvez le voir iciComment supprimer les variables de classe à usage unique du code Objective-C?

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

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

, le rappel actionSheet clickedButtonAtIndex ne me permet pas de passer le activeField donc je dois utiliser une variable de classe. Il semble plus correct d'écrire ceci:

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

Je crois que je peux le sous-classe UIActionSheet et UIActionSheet délégué et ajouter les signatures que j'ai besoin, mais encore une fois cela semble plus d'effort que cela vaut la peine (?). Donc, ma question est quelle est la meilleure façon de faire ce que je suis en train de faire? Je ne veux pas nécessairement changer l'interface de sélecteur de date/feuille d'action que j'ai créée (bien que s'il y ait un meilleur modèle pour placer plusieurs dates sur un UIView tout en gardant le DatePicker à l'écart, je '' . m toutes les oreilles)

Répondre

3

Dans ce cas, je pense une sous-classe simple UIActionSheet serait la voie à suivre:

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

@implementation SpecialActionSheet 
@synthesize parameter; 
@end 

cela devrait être suffisant, car tout ce que vous voulez faire est d'avoir le actionSheet garder un paramètre. Maintenant, votre code peut se présenter comme suit:

- (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

Mon approche habituelle dans ces situations est d'utiliser la propriété de balise sur UIAlertViews, et faire un interrupteur sur (il est un entier). Ce n'est pas aussi bien que d'avoir une chaîne ou quelque chose à transmettre, mais si vous avez plusieurs alertes, c'est un moyen facile de les désamorcer. Par exemple:

... 
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

Je n'étais pas au courant de la propriété tags. Je vais devoir regarder ça. –

2

Une autre solution consiste à use associative storage.

UIActionSheet pourrait déjà avoir. Vous pouvez le tester par

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

Le stockage associatif est plutôt astucieux s'il n'est pas surutilisé.