【问题标题】:How to notify ViewController on parse end with multiple ViewControllers using a single parser如何使用单个解析器通过多个 ViewController 在解析结束时通知 ViewController
【发布时间】:2010-05-16 15:56:33
【问题描述】:

我创建了一个 RSS 解析器和 3 个 TableView,它可以很好地解析 RSS 文件,但我不知道如何在解析结束时通知 TableViewController 以便它可以更新视图。 TableViewController 启动解析器和提要的解析。

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

我可以访问单个提要项目,例如

[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 初学者的欢呼。

【问题讨论】:

    标签: iphone objective-c nsxmlparser


    【解决方案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】:

    如果您需要将单个事件通知多个对象,则委托方法通常会开始变得混乱。

    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 定义的名称) 并被告知。

    这是一个简短的介绍:)

    【讨论】:

    • 对不起,控制器应该只被通知它自己的 RSSParser 实例。
    • 附加组件:我想在调用 parserDidEndDocument 时以某种方式运行 [mytableview reloadData]。
    • 啊,好吧,那么你想要委托模式:) 我会把它添加到我的答案中。
    • 谢谢朋友,感谢您的帮助。
    【解决方案3】:

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

    • NSNotifications。易于实现,但并不总是很好的可维护性(您永远不知道哪个对象注册到您的通知中)
    • 委托数组(而不是单个委托),并在数组的每个对象上调用委托方法。 Three20 经常使用这种模式(Three20 是一个很好的参考),但看起来代理模式仍然被拉伸得太远了,恕我直言。
    • Key-Value Observing 在您的数据对象上。例如,如果您的模型上有一个属性“RSSItems”,其中包含已解析的 RSS 数据,您将注册每个控制器以侦听 RSSItems 对象的更改:

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

    然后,在您的parser:didEndElement: 方法中,您将设置RSSItem 的内容,从而触发KVO 通知。

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-02-16
      • 2012-09-23
      • 1970-01-01
      • 2023-03-08
      • 2017-12-29
      • 2012-11-14
      • 2012-03-23
      • 1970-01-01
      相关资源
      最近更新 更多