2009-12-09 12 views
2

J'ai une classe qui appelle une autre classe à analyser (NSXMLParse) à partir d'une URL. Maintenant, je voudrais que la classe appelant celui-ci sache quand elle a fini, afin que je puisse remplir l'interface utilisateur. Je suppose qu'un délégué serait le chemin à parcourir, mais je n'ai jamais travaillé avec un délégué et j'aurais besoin de conseils sur la façon de le brancher.Objective-C Delegates: J'ai une autre classe que j'appelle qui analyse XML. Besoin de savoir quand cela est fait en externe

Merci

Répondre

3

Fondamentalement, la délégation signifie simplement donner un objet un pointeur à quelque chose dont il a besoin de parler de ce qu'il fait. Dans Cocoa, ceci est généralement traité par des "protocoles", qui sont en quelque sorte l'inverse d'une déclaration d'interface: ils décrivent les méthodes qu'un objet appellera sur un autre objet qui "implémente" le protocole. Ils ne sont pas, à proprement parler, nécessaires, particulièrement dans une situation aussi simple que celle-ci, mais ce sont de bonnes pratiques et c'est une bonne chose de savoir si vous allez écrire du code modulaire.

Dans l'en-tête de la classe d'analyse syntaxique:

// This is the protocol declaration; anything implementing the "ParsingDelegate" protocol needs to have any method signatures listed herein 
@protocol ParsingDelegate 
- (void)parsingDidEndWithResult:(NSDictionary *)result 
@end 

@interface ParsingClass : NSObjectOrWhatever 
{ 
     ... 
     id<ParsingDelegate> _delegate; 
} 
... 
// We'll use this property to tell this object where to send its messages 
@property(nonatomic,assign) id<ParsingDelegate> delegate; 
@end 

Dans la mise en œuvre de l'analyseur:

@implementation ParsingClass 
@synthesize delegate=_delegate; 
// the "=_delegate" bit isn't necessary if you've named the instance variable without the underscore 
... 

Dans la méthode dans laquelle l'analyseur termine sa substance:

... 
// make sure the delegate object responds to it 
// assigning an object that doesn't conform to the delegate is a warning, not an error, 
// but it'll throw a runtime exception if you call the method 
if(self.delegate && [self.delegate respondsToSelector:@selector(parsingDidEndWithResult:)]) 
{ 
     [self.delegate performSelector:@selector(parsingDidEndWithResult:) withObject:someResultObject]; 
} 
... 

Dans l'interface utilisateur en-tête de la classe:

@interface SomeUIClass : NSObjectOrWhatever <ParsingDelegate> 

Dans la classe de l'interface utilisateur, partout où il met en place l'analyseur,

parser.delegate = self; 

puis mettre en œuvre la méthode juste -parsingDidEndWithResult: sur la classe de l'interface utilisateur. Si plusieurs analyseurs s'exécutent en même temps, vous pouvez étendre la méthode déléguée pour transmettre l'objet analyseur lui-même - c'est un peu le standard Cocoa - mais pour le cas que vous avez décrit, cela devrait faire l'affaire.

+1

Merci pour votre detaile d explication. doit être l'explication la plus concise et pourtant détaillée jusqu'à présent. J'ai des tonnes de livres et ça ne l'explique toujours pas aussi clairement.Bravo – Doz

+0

Le seul problème que j'ai, c'est qu'il y a deux avertissements: (1) respondsToSelector introuvable dans le protocole (2) performSelector non trouvé dans le protocole. Avons-nous oublié quelque chose dans la déclaration protocolaire? – Doz

+1

Vous avez raison-'- respondsToSelector' et' -performSelector' sont les deux méthodes sur 'NSObject', et ne s'appliquent évidemment pas à' id', qui n'a pas d'interface. Je pense que 'id ' serait la syntaxe correcte pour déclarer qu'un objet doit adhérer à plusieurs protocoles. –

1

Vous avez principalement 3 façons de parler dans le cacao: délégués, notifications et KVO. (cf http://alexvollmer.com/index.php/2009/06/24/cocoas-ways-of-talking/)

Je suppose que vous récupérez les données et que vous analysez le code XML dans un thread d'arrière-plan. Donc quelle que soit la solution que vous allez utiliser, gardez à l'esprit de mettre à jour l'interface utilisateur dans mainthread (en utilisant performSelectorOnMainThread par exemple)

5

NSNotification est, à mon avis, le moyen le plus simple de configurer quelque chose comme ça.

Ceci est un petit extrait d'une de mes applications:

dans method.m quand quelque chose que je suis le traitement a terminé

[[NSNotificationCenter defaultCenter] postNotificationName:@"GlobalTagsReady" object:nil]; 

dans la classe pour prendre soin de la notification

[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(getTags) name:@"GlobalTagsReady" object:nil]; 

@selector(getTags) est la méthode à appeler

+0

Un autre bon point, cela semble plus facile mais quelle est la meilleure méthode de pratique, les notifications ou les délégués? – Doz

+0

Les notifications ont tendance à être utilisées lorsque vous avez plusieurs écouteurs non liés et des délégués lorsque vous avez des relations en tête-à-tête. – nico