2010-05-16 62 views
0

我已经创建了一个RSS解析器和3个TableViews,它解析RSS文件很好,但我不知道如何通知TableViewController解析已结束,所以它可以更新视图。 TableViewController启动解析器和解析馈送。如何使用一个解析器通知ViewController与多个ViewControllers

parser = [[RSSParser alloc] initWithURL:@"http://randomfeed.com"]; 

我可以访问单一的饲料项目,如

[parser feedItems]; 

在parser.mi已经实施的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初学者的欢呼声。

回答

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,它会实例化手臂,拨号等等。它们都会被链接到时钟并使用这种模式提醒时钟控制器他们的动作。这样我就可以使用时钟臂或按照其他代码拨号,只要实例化它们的对象遵守ClockArmDelegate协议即可。

希望它是有道理的:)它是,我很肯定,最可用的可可模式。

+0

感谢这个例子,让我明白如何充分使用它。 – mbogh 2010-05-16 18:54:31

1

如果您需要多个对象来通知单个事件,那么委托方法通常会变得杂乱无章。

NSNotifications是一个很好的选择。

[[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定义的名称) 和控制器的通知。

这是一个短期内,通过:)

+0

对不起,我的控制器只能通知它自己的RSSParser实例。 – mbogh 2010-05-16 16:22:44

+0

附加组件:我想在调用parserDidEndDocument时以某种方式运行[mytableview reloadData]。 – mbogh 2010-05-16 16:46:25

+0

嗯好的,那么你想要委托模式:)我会将它添加到我的答案。 – RickiG 2010-05-16 17:39:42

0

我在这里看到的三种可能的解决方案:

  • NSNotifications。易于实现,但并不总是很好的可维护性(您永远不知道哪个对象注册到您的通知)
  • 代表数组(而不是一个委托),并调用阵列的每个对象上的委托方法。 Three20使用这种模式很多(Three20是一个很好的参考),但它仍然看起来像代表模式被拉得太远,恕我直言。
  • 键值观察对您的数据对象。举例来说,如果你有你的模型中的财产“的RSSItems”包含解析RSS数据,你会登记每个控制器的侦听更改的RSSItems对象:

    [rssParser addObserver:yourViewController 
          forKeyPath:@"RSSItems" 
           options:NSKeyValueObservingOptionNew 
           context:NULL]; 
    

然后,在你的parser:didEndElement:方法,你可以设置RSSItem的内容,从而触发KVO通知。

我认为这第三个选项是最好的:它是一个标准的Cocoa机制,它不需要系统范围的通知,也不会将委托模式拉得太远。

相关问题