Objective-C Delegates: Have another class I call that parses XML. Need to know when its done externally
I have a class tha开发者_JAVA百科t calls another class to parse (NSXMLParse) from a URL. Now I would like for the class calling this one to know when it has finished, so that I can populate the UI. I am guessing a delegate would be the way to go but ive never worked with one and would need some guidance as to how this would be wired.
Thanks
NSNotification is, in my opinion, the easiest way to setup something like this.
This is a small snippet from one of my apps:
in method.m when the something I'm processing has finished
[[NSNotificationCenter defaultCenter] postNotificationName:@"GlobalTagsReady" object:nil];
in the class to take care of the notification
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(getTags) name:@"GlobalTagsReady" object:nil];
where @selector(getTags)
is the method to be called
Basically, delegation just means giving an object a pointer back to something that it needs to tell about what it's doing. In Cocoa, this is usually handled through “protocols”, which are sort of the reverse of an interface declaration: they describe what methods an object will call on another object that “implements” the protocol. They're not, strictly speaking, necessary, particularly in a simple situation like this, but they're good practice and a good thing to know if you're going to be writing modular code.
In the parsing class's header:
// 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
In the parser's implementation:
@implementation ParsingClass
@synthesize delegate=_delegate;
// the "=_delegate" bit isn't necessary if you've named the instance variable without the underscore
...
In the method in which the parser finishes its stuff:
...
// 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];
}
...
In the UI class's header:
@interface SomeUIClass : NSObjectOrWhatever <ParsingDelegate>
In the UI class, wherever it sets up the parser,
parser.delegate = self;
then just implement the -parsingDidEndWithResult:
method on the UI class. If you have multiple parsers running at once, you might want to extend the delegate method to pass in the parser object itself—that's kind of the Cocoa standard—but for the case you've described, this should do the trick.
You mainly got 3 ways to talk in cocoa: delegates, notifications and KVO. (cf http://alexvollmer.com/index.php/2009/06/24/cocoas-ways-of-talking/)
I assume that you are fetching the data and parsing the XML in a background thread. So whatever solution you are going to use, keep in mind to update the UI in the mainthread (using performSelectorOnMainThread for instance)
精彩评论