t6d*_*t6d 5 iphone asynchronous objective-c uitableview grand-central-dispatch
我有一个UITableViewController,我想通知一次相应的模型的数据已经能够显示.问题是这些数据是从Web服务获取的,请求可能需要几秒钟.目前,我正在主线程上同步获取数据,这当然导致我的主线程被阻塞.现在,我不希望我的控制器知道有关从互联网下载数据的任何信息.我怎样才能做到这一点.目前,我正在考虑使用GCD并实现类似的方法,-loadDataWithCallback:并提供一个触发[tableView reloadData]成功的回调.这是一个好方法吗?是否有其他可能通知控制器模型准备好了?我的另一个想法是使用委托机制并将控制器设置为我的模型的委托?
总结一下,有什么更好的:带回调的GCD或实现自己的委托机制?
还有其他可能吗?
更新:2011年6月24日13:15 CET
阅读完所有回复后,我得出结论,我的问题有三种可能的解决方案:
利用NSNotifications并使用NSURLConnection实现异步.下载
实现自定义协议并使用委派机制.再次,用于NSURLConnection实现异步.下载.
在单独的GCD队列中使用同步下载并使用回调.
由于没有人赞成最后的解决方案,我想深入讨论这种方法.在看到通知处理中涉及的所有代码之后,我认为GCD是一种更好的方法.而不是同意某个必须以某种方式记录的通知,以便每个开发人员都知道它,我可以简单地使用回调.一方面,它给了我一个清晰的界面,就像我在使用代表时所拥有的那样,另一方面,它给了我完全的灵活性.你真的认为GCD要复杂吗?这是我的代码:
- (void)loadRestaurantsWithCallback:(void (^)())callback
{
dispatch_queue_t current_queue = dispatch_get_current_queue();
dispatch_queue_t download_queue = dispatch_queue_create("Download queue", NULL);
dispatch_async(download_queue, ^{
self.restaurants = [self loadRestaurants];
dispatch_async(current_queue, ^{ callback(); });
});
dispatch_release(download_queue);
}
Run Code Online (Sandbox Code Playgroud)
顺便说一句,我的应用程序只显示我大学不同食堂的菜单.
在我的控制器中,我只是执行以下操作:
if (![self.canteen hasRestaurants]) {
[self.canteen loadRestaurantsWithCallback:^{
[self.tableView reloadData];
}];
}
Run Code Online (Sandbox Code Playgroud)
它就像一个魅力.您对此解决方案有何看法?
更新:2011年6月24日16:30 CET
这个问题有第四种解决方案,即使它涉及的代码多于GCD方法,也可能是这样的方法.这是我想出的:
用于NSURLConnection进行异步下载.
让您的模型响应NSURLConnection实例发送的回调.
使用键值编码和键值观察.
在您的控制器中,您只需执行以下操作:
[self.model addObserver:self forKeyPath:@"method-name" options:0 context:NULL];
Run Code Online (Sandbox Code Playgroud)
和
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
{
[self.tableView reloadData];
}
Run Code Online (Sandbox Code Playgroud)
使用NSNotificationCenter并创建本地通知类型并在获取数据后发布它的最佳方法。
首先注册通知类型DataUpdateNotification。
- (void)viewWillAppear:(BOOL)animated
{
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(receiveDataNotification:)
name:@"DataUpdateNotification"
object:nil];
...............
}
Run Code Online (Sandbox Code Playgroud)
实现 receiveDataNotification: 来处理DataUpdateNotification类型通知。
- (void) receiveDataNotification:(NSNotification *) notification
{
if ([[notification name] isEqualToString:@"DataUpdateNotification"])
{
NSLog (@"Successfully received the Data Update notification!");
}
}
Run Code Online (Sandbox Code Playgroud)
当控制器消失时,从对象实例中删除通知。
- (void)viewWillDisappear:(BOOL)animated
{
[[NSNotificationCenter defaultCenter] removeObserver:self];
}
Run Code Online (Sandbox Code Playgroud)
现在从应用程序的任何部分发布通知..
- (void) DataUpdated
{
[[NSNotificationCenter defaultCenter] postNotificationName:@"DataUpdateNotification" object:self];
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
872 次 |
| 最近记录: |