2017-05-03 1 views
3

J'ai un très petit projet Xcode avec plusieurs contrôleurs de vue. Je me suis retrouvé dupliquer les méthodes suivantes dans les:Quand est-il acceptable de réduire la duplication de code en plaçant le code dans AppDelegate?

- (void)postTip:(NSString *)message { 
    [self postInfoAlertWithTitle:@"Tip" andMessage:message andAction:@"Got it!"]; 
} 

- (void)postInfoAlertWithTitle:(NSString *)title andMessage:(NSString *)message andAction:(NSString *)action { 
    UIAlertController *alert = [UIAlertController alertControllerWithTitle:title message:message preferredStyle:UIAlertControllerStyleAlert]; 
    [alert addAction:[UIAlertAction actionWithTitle:action style:UIAlertActionStyleDefault handler:nil]]; 
    [self presentViewController:alert animated:YES completion:nil]; 
} 

Bien sûr, cela m'a fait penser à la façon dont je pourrais retirer (ou au moins réduire) le code dupliquée.

La réponse évidente est de placer le comportement souhaité dans une classe parente, puis de faire en sorte que mes contrôleurs de vues héritent de cette classe. Cependant, certains des contrôleurs de vue sont de type UICollectionViewController et certains sont de type UITableViewController, et je ne sais pas comment conserver leurs attributs de collection et de table, respectivement, au cas où je hériterais d'un hypothétique MyViewController is-a UIViewController. J'ai donc fait un peu de recherche et jeté un coup d'oeil sur les protocoles. Initialement, cela semblait être un bon ajustement, sauf que vous ne pouvez pas fournir une implémentation par défaut pour les méthodes déclarées dans un protocole, ce qui est essentiellement ce que je voudrais.

Enfin, et avec beaucoup d'hésitation et de haine de soi, je considérais placer le comportement dans ma classe de AppDelegate, avec un paramètre supplémentaire pour faciliter la présentation des alertes:

- (void)postTip:(NSString *)message toController:(UIViewController *)controller; 
- (void)postInfoAlertWithTitle:(NSString *)title andMessage:(NSString *)message andAction:(NSString *)action toController:(UIViewController *)controller; 

Un appel dans un look de contrôleur de vue donné comme ceci:

[self.appDelegate postTip:@"Git gud!" toController:self]; 

Et voila! Le comportement que je veux, où je le veux, et tout ce que je dois faire pour obtenir une instance de l'AppDelegate! Mais ... ça ne me va pas bien. Il semble ... malodorant. De plus, il y a encore de la duplication, c'est-à-dire déclarer et initialiser une propriété appDelegate privée, ce que j'ai pris soin de faire plutôt que d'appeler le délégué [AppDelegate *] [[UIApplication sharedApplication]] où:

  • je précise « faible » et éviter possible de conserver les cycles
  • je prends un seul pointeur vers le AppDelegate (hourra pour l'optimisation prématurée>. <)

Est-il considéré comme acceptable d'utiliser AppDelegate comme référentiel pour le comportement à l'échelle de l'application comme les méthodes d'utilité, et si oui, suis-je inutilement Il est paranoïaque à propos de la mise en œuvre re: en utilisant une propriété? (Si non, quelles sont mes options?)

+4

Créez une catégorie sur 'UIViewController', qui aura les méthodes (les initiales, pas celles de AppDelegate). 'UICollectionViewController' et' UITableViewController' héritent de 'UIViewController', donc ça devrait aller. Évitez d'utiliser votre AppDelegate comme cela en ajoutant trop d'informations sans rapport. Ce que vous utilisez en réalité est le fait que c'est un singleton (qui peut être fait par vous-même). – Larme

+1

Vous pouvez créer une classe "TipHelper" et utiliser une instance (ou une instance partagée) dans vos différents contrôleurs. Puisque l'héritage n'est pas une option facile pour vous, la composition est une autre stratégie disponible. –

+0

Larme - Ahhh, je ne connaissais pas les catégories! Très intéressant, et, je pense, juste le billet! – kuipersn

Répondre

0

Il me semble que les catégories étaient destinées exactement à ce genre de situation - mais comme d'autres l'ont souligné dans les commentaires, il y a des options supplémentaires - et c'est ce que J'ai fait.

Pour afficher la documentation de la catégorie Apple, voir this page. Pour ajouter une catégorie dans Xcode, voir this page.

1

certainement utiliser une catégorie en créant .h et les fichiers .m

UIViewController + InfoAlert.h

@interface UIViewController (InfoAlert) 

- (void)postInfoAlertWithTitle:(NSString *)title andMessage:(NSString *)message andAction:(NSString *)action; 

@end 

UIViewController + InfoAlert.m

#import "UIViewController+InfoAlert.h" 

@implementation UIViewController (InfoAlert) 

- (void)postInfoAlertWithTitle:(NSString *)title andMessage:(NSString *)message andAction:(NSString *)action { 
    UIAlertController *alert = [UIAlertController alertControllerWithTitle:title message:message preferredStyle:UIAlertControllerStyleAlert]; 
    [alert addAction:[UIAlertAction actionWithTitle:action style:UIAlertActionStyleDefault handler:nil]]; 
    [self presentViewController:alert animated:YES completion:nil]; 
} 

@end 

alors il suffit d'importer votre UIViewController + InfoAlert.h où vous voulez utiliser votre nouvelle méthode postInfoAlertWithTitle