我已经创建了一个RSS解析器和3个TableViews,它可以很好地解析RSS文件,但是我不知道如何在解析结束时通知TableViewController,这样它就可以更新视图。 TableViewController启动解析器和解析feed。
parser = [[RSSParser alloc] initWithURL:@"http://randomfeed.com"];
我可以访问单个Feed项目,例如
[parser feedItems];
在parser.m中,我实现了NSXMLParser的委托方法:
- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qualifiedName attributes:(NSDictionary *)attributeDict
- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string
- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName
- (void)parserDidEndDocument:(NSXMLParser *)parser
那么如何让parserDidEndDocument通知我的控制器,以便我可以将数据添加到tableview。
来自obj-c初学者的欢呼。
答案 0 :(得分:1)
如果您需要多个对象通知单个事件,则委托方法通常会开始变得混乱。
NSNotification是一个很好的选择。
[[NSNotificationCenter defaultCenter] addObserver: self selector: @selector(reachabilityChanged:) name: kInternetAvailableNotification object: nil];
上面为当前对象添加了一个“监听器”,用于侦听任何触发它的人 kInternetAvailableNotification通知。当事件发生时,调用方法“reachabilityChanged”。
在你的dealloc方法中,记得取消注册通知:
- (void)dealloc {
[[NSNotificationCenter defaultCenter]
removeObserver:self
name:kInternetAvailableNotification
object:nil];
[super dealloc];
}
您的代码中的任何地方现在都可以通知侦听器某个事件:
[[NSNotificationCenter defaultCenter]
postNotificationName:kInternetAvailableNotification
object:nil];
NSNotifications可以发送带有对象的字典 听众可以使用。
因此,每个需要知道新数据何时可用的控制器都可以注册 kInternetAvailableNotification通知(它只是一个由NSString定义的名称) 并被告知。
这是一个简短的贯通:)
答案 1 :(得分:1)
好的,委托模式在Cocoa框架中被广泛使用。
解析数据的文件必须具有协议,任何想要回调的人都会形成这个协议 类必须实现协议中的方法:
//XMLParser.h
//import statements here ..
@protocol XMLParserDelegate
- (void) parserDidFinish:(NSArray*) theParsedData; //have as many methods as you please, didFail, doingProgress etc.
@end
@interface XMLParser : NSObject {
id <XMLParserDelegate> delegate; //we don't know what type of object this will be, only that it will adhere to the XMLParserDelegate protocol.
}
@property(assign) id delegate;
//methods
@end
在XMLParser的实现中:
@implementation XMLParser
@synthesize delegate;
- (void)parserDidEndDocument:(NSXMLParser *)parser {
[self.delegate parserDidFinish:dataYouCollectedArray]; //this is where it happens.
}
因此,在您的控制器界面文件中,您说您将遵守XMLParserDelegate协议。
//MyController.h
#import "XMLParser.h"
@interface MyController : UIViewController <XMLParserDelegate> { //this is where you "promise" to implement the methods of the protocol.
}
在MyController.m文件中,您现在可以实例化XMLParser。
@implementation MyController
- (void) init {
XMLParser *parser = [[XMLParser alloc] init];
[parser setDelegate:self] //now the parser has a reference to this object.
[parser start];
}
- (void) parserDidFinish:(NSArray*) results {
//now you have your results in the controller, can set it as the data source of the tableView and call tableView.reloadData;
}
这是一个很好的模式,它可以松散地与呼叫者和响应者结合,而不会让他们知道协议所规定的任何其他内容。
如果我的视图元素仅限于其自身的功能,例如时钟。 我会有一个ClockViewController,它会实例化arm,dials等。它们都会链接到时钟并使用这种模式提醒时钟控制器他们的行为。这样我可以使用时钟臂或拨打其他代码,只要实例化它们的对象遵守ClockArmDelegate协议。
希望它有道理:)它是我非常肯定的,在Cocoa中最常用的模式。
答案 2 :(得分:0)
我在这里看到三种可能的解决方案:
键值观察。例如,如果模型上包含已解析的RSS数据的属性“RSSItems”,则应注册每个控制器以侦听对RSSItems对象的更改:
[rssParser addObserver:yourViewController
forKeyPath:@"RSSItems"
options:NSKeyValueObservingOptionNew
context:NULL];
然后,在您的parser:didEndElement:
方法中,您将设置RSSItem的内容,从而触发KVO通知。
我认为第三种选择是最好的:它是一种标准的Cocoa机制,它不需要系统范围的通知,也不会过多地延长委托模式。