Comment réaliser des fonctions de call back en Objective-C ?
Je voudrais juste voir quelques exemples complets et je devrais comprendre.
Comment réaliser des fonctions de call back en Objective-C ?
Je voudrais juste voir quelques exemples complets et je devrais comprendre.
Pour être complet, puisque le RSS de StackOverflow a ressuscité la question pour moi par hasard, l'autre option (plus récente) consiste à utiliser des blocs :
@interface MyClass: NSObject
{
void (^_completionHandler)(int someParameter);
}
- (void) doSomethingWithCompletionHandler:(void(^)(int))handler;
@end
@implementation MyClass
- (void) doSomethingWithCompletionHandler:(void(^)(int))handler
{
// NOTE: copying is very important if you'll call the callback asynchronously,
// even with garbage collection!
_completionHandler = [handler copy];
// Do stuff, possibly asynchronously...
int result = 5 + 3;
// Call completion handler.
_completionHandler(result);
// Clean up.
[_completionHandler release];
_completionHandler = nil;
}
@end
...
MyClass *foo = [[MyClass alloc] init];
int x = 2;
[foo doSomethingWithCompletionHandler:^(int result){
// Prints 10
NSLog(@"%i", x + result);
}];
Normalement, les callbacks en Objective C sont faits avec des délégués. Voici un exemple d'implémentation d'un délégué personnalisé ;
Fichier d'en-tête :
@interface MyClass : NSObject {
id delegate;
}
- (void)setDelegate:(id)delegate;
- (void)doSomething;
@end
@interface NSObject(MyDelegateMethods)
- (void)myClassWillDoSomething:(MyClass *)myClass;
- (void)myClassDidDoSomething:(MyClass *)myClass;
@end
Fichier d'implémentation (.m)
@implementation MyClass
- (void)setDelegate:(id)aDelegate {
delegate = aDelegate; /// Not retained
}
- (void)doSomething {
[delegate myClassWillDoSomething:self];
/* DO SOMETHING */
[delegate myClassDidDoSomething:self];
}
@end
Cela illustre l'approche générale. Vous créez une catégorie sur NSObject qui déclare les noms de vos méthodes de callback. NSObject n'implémente pas réellement ces méthodes. Ce type de catégorie est appelé un protocole informel, vous dites simplement que de nombreux objets pourraient implémenter ces méthodes. C'est un moyen de déclarer à l'avance la signature de type du sélecteur.
Ensuite, un objet est le délégué de "MyClass" et MyClass appelle les méthodes du délégué comme il convient. Si vos rappels de délégués sont optionnels, vous les garderez typiquement au site de distribution avec quelque chose comme "if ([delegate respondsToSelector:@selector(myClassWillDoSomething :)) {". Dans mon exemple, le délégué doit mettre en œuvre les deux méthodes.
Au lieu d'un protocole informel, vous pouvez également utiliser un protocole formel défini avec @protocol. Si vous faites cela, vous changerez le type du délégué, du setter et de la variable d'instance pour qu'ils soient " id <MyClassDelegate>
" au lieu de simplement " id
".
Aussi, vous remarquerez que le délégué n'est pas retenu. C'est généralement le cas parce que l'objet qui "possède" les instances de "MyClass" est également le délégué. Si MyClass conservait son délégué, il y aurait alors un cycle de conservation. C'est une bonne idée, dans la méthode dealloc d'une classe qui possède une instance de MyClass et qui est son délégué, d'effacer la référence du délégué puisque c'est un back pointer faible. Sinon, si quelque chose maintient l'instance de MyClass en vie, vous aurez un pointeur suspendu.
+1 Bonne réponse approfondie. La cerise sur le gâteau serait un lien vers une documentation plus approfondie d'Apple sur les délégués :-)
Jon, merci beaucoup pour votre aide. J'apprécie vraiment votre aide. Je suis désolé, mais je ne suis pas très clair sur la réponse. Message .m est une classe qui se définit comme le délégué pendant l'appel de la fonction doSomething. DoSomething est-elle la fonction de rappel que l'utilisateur appelle ? car j'ai l'impression que l'utilisateur appelle doSomething, et que vos fonctions de rappel sont myClassWillDoSomethingg & myClassDidDoSomething. De même, pouvez-vous me montrer comment créer une classe supérieure qui appelle la fonction de rappel. Je suis un programmeur C et je ne suis donc pas encore très familier avec l'environnement Obj-C.
"Message .m" signifie simplement, dans votre fichier .m. Vous auriez une classe séparée, appelons-la "Foo". Foo aurait une variable "MyClass *myClass", et à un moment donné, Foo dirait "[myClass setDelegate:self]". À n'importe quel moment après cela, si quelqu'un, y compris foo, invoquait la méthode doSomethingMethod sur cette instance de MyClass, foo aurait ses méthodes myClassWillDoSomething et myClassDidDoSomething invoquées. Je vais également poster un deuxième exemple différent qui n'utilise pas de délégués.
Voici un exemple qui ne tient pas compte des concepts de délégués et qui se contente d'un rappel brut.
@interface Foo : NSObject {
}
- (void)doSomethingAndNotifyObject:(id)object withSelector:(SEL)selector;
@end
@interface Bar : NSObject {
}
@end
@implementation Foo
- (void)doSomethingAndNotifyObject:(id)object withSelector:(SEL)selector {
/* do lots of stuff */
[object performSelector:selector withObject:self];
}
@end
@implementation Bar
- (void)aMethod {
Foo *foo = [[[Foo alloc] init] autorelease];
[foo doSomethingAndNotifyObject:self withSelector:@selector(fooIsDone:)];
}
- (void)fooIsDone:(id)sender {
NSLog(@"Foo Is Done!");
}
@end
En général, la méthode -[Foo doSomethingAndNotifyObject:withSelector :] serait asynchrone, ce qui rendrait le rappel plus utile qu'il ne l'est ici.
Merci beaucoup John. Je comprends votre première implémentation de callback après vos commentaires. De même, votre deuxième implémentation de callback est plus simple. Les deux sont très bien.
Pour que cette question reste d'actualité, l'introduction dans iOS 5.0 de la fonction ARC cela peut être réalisé en utilisant Blocs de manière encore plus concise :
@interface Robot: NSObject
+ (void)sayHi:(void(^)(NSString *))callback;
@end
@implementation Robot
+ (void)sayHi:(void(^)(NSString *))callback {
// Return a message to the callback
callback(@"Hello to you too!");
}
@end
[Robot sayHi:^(NSString *reply){
NSLog(@"%@", reply);
}];
Il y a toujours Syntaxe du bloc F****ng si jamais vous oubliez la syntaxe Block d'Objective-C.
CallBack : Il existe 4 types de callback en Objective C
Type de sélecteur : Vous pouvez voir que NSTimer,UIPangesture sont les exemples de Selector callback. Utilisé pour une exécution très limitée du code.
Type de délégué : Communs et les plus utilisés dans le framework Apple. UITableViewDelegate, NSNURLConnectionDelegate. Ils sont généralement utilisés pour montrer le téléchargement asynchrone de nombreuses images depuis le serveur, etc.
NSNotifications : NotificationCenter est une des fonctionnalités d'Objective C qui permet de notifier plusieurs destinataires au moment où un événement se produit.
Blocs : Les blocs sont plus couramment utilisés en programmation Objective C. C'est une fonctionnalité intéressante qui permet d'exécuter des morceaux de code. Vous pouvez également vous référer au tutoriel pour comprendre : Tutoriel sur les blocs
S'il vous plaît laissez-moi si une autre réponse pour cela. Je vous en serai reconnaissant.
Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.