2013-09-22 3 views
0

Je suis en train de concevoir une nouvelle application en modernisant le code que j'ai écrit dans le passé. Cet ancien code utilise le modèle class/delegate et j'essaie de les transformer pour utiliser des blocs comme callback, pas pour les tâches déléguées.Faire Xcode se plaindre d'un paramètre manquant

Ce que je fais est de créer une propriété comme

@property (nonatomic, copy) void (^onTouch)(NSInteger index); 

qui passerait à l'objet en utilisant cette classe un bloc où le code peut être inséré et dans ce cas exécuté au toucher.

Mais mon problème est le suivant. Lorsque vous utilisez des délégués et que vous avez une méthode sur le protocole de délégué, Xcode vous avertira si vous utilisez cette classe et oublie d'implémenter les protocoles de délégué. Est-ce un moyen de le faire avec des blocs? Ou en d'autres termes: existe-t-il un moyen de faire se plaindre Xcode si un bloc de rappel n'est pas défini par l'appelant?

Je veux dire que ce serait le bon:

MyClass *obj = [[MyClass alloc] init]; 
obj.onTouch = ^(NSInteger *index){ //call back code to be executed }; 

Ce serait bien aussi

MyClass *obj = [[MyClass alloc] init]; 
obj.onTouch = nil; 

mais cela générerait un message

MyClass *obj = [[MyClass alloc] init]; 
// no callback block defined. 

Est-ce possible?

Répondre

2

Si vous voulez appliquer un certain paramètre, je l'inclurais dans l'initialiseur.

MyClass *obj = [[MyClass alloc] initWithBlock:^(NSInteger *index) { /* code*/ }]; 

Puis, en MyClass:

- (id)init { 
    // This will result in a runtime error if you use the wrong initializer. 
    NSAssert(NO, @"Use initWithBlock instead."); 
} 

- (id)initWithBlock(initWithBlock:^(NSInteger *)block) { 
    self = [super init]; 
    if (self) { 
    self.onTouch = block; 
    } 
    return self; 
} 

Notez également, en essayant d'exécuter un NULL résultats de bloc dans un accident, alors assurez-vous de le faire:

if (self.onTouch) { self.onTouch(); } 

Où que vous exécutez le bloc.

+0

ahhh, c'est une idée excellente !!!!!!!!! Je pensais à un délégué avec des méthodes de délégués multiples contre plusieurs blocs, mais votre idée garantit au moins un bloc sur l'init si je le veux compact ou je peux avoir une ligne d'init de long mile pour inclure plusieurs blocs ... de toute façon l'idée est excellent. – SpaceDog

1

D'abord, je recommande fortement defining types to represent your blocks - les rend beaucoup plus faciles à travailler, surtout si vous avez besoin de refactoriser les paramètres.

Vous ne pouvez pas écrire de code qui distingue "Je n'ai pas défini cette propriété" ou "Le moteur d'exécution a initialisé cette propriété à zéro", du moins pas sans code d'exécution folle pour vérifier la pile. Seule l'option que je peux penser serait d'utiliser le null object pattern. Avant d'élaborer, gardez à l'esprit que je n'ai pas essayé de tester cela, mais cela devrait fonctionner. Définissez un bloc qui signifie 'n'a pas de valeur' ​​et définissez votre propriété pour qu'elle pointe vers ce bloc sur init. Ensuite, vous pouvez comparer à NullBlock à l'exécution pour identifier si quelqu'un a explicitement mis la propriété à zéro (parce qu'il serait nul à ce moment) ou lui donner une valeur réelle non nulle. Alternativement, si cela ne vous dérange pas d'écrire manuellement vos accesseurs set, vous pourriez avoir un BOOL qui suit si quelqu'un a explicitement défini la propriété. Ensuite, lorsque vous appelez le bloc, vérifiez si quelqu'un a réellement défini la valeur ou non.

@synthesize onTouchBlock=_onTouchBlock; 
MyBlock _onTouchBlock; 
BOOL _onTouchBlockWasSet; 

- (void)setOnTouchBlock:(MyBlock)block { 
_onTouchBlockWasSet = YES; 
_onTouchBlock = block; 
} 

Je ne recommanderais pas passer la valeur dans le initialiseur parce qui le rend lié à la création de ce type d'objet.Si vous vouliez changer le code en fonction de certaines conditions, vous reviendrez à la case départ. En outre, cela vous empêche d'utiliser des storyboards qui créent cet objet.

+0

Merci pour ces belles idées !!!! – SpaceDog

Questions connexes