在我的应用程序中,我有一个UITableViewController。
它的tableView分为3个部分。
我从服务器下载每个部分的数据。为此,我有3个函数(例如f1 f2和f3)。每个都更新一个相应的NSArray,用作我的表的数据源。
现在我想要的是使用这个函数重新加载数据,并在完成这3个功能后刷新我的tableView,但不会打扰用户。
我没有使用异步请求,块,线程等......而且我正在寻找提示。
实际上,这就是我的工作:
-(void)viewDidLoad
{
//some settings
[NSTimer scheduledTimerWithTimeInterval:15.0 target:self selector:@selector(reloadDatas) userInfo:nil repeats:YES];
dispatch_queue_t queue = dispatch_get_main_queue();
dispatch_async(queue, ^{
[self reloadDatas];
});
}
-(void)reloadDatas
{
dispatch_queue_t concurrentQueue = dispatch_get_main_queue();
dispatch_async(concurrentQueue, ^{
[self f1];
[self f2];
[self f3];
[myDisplayedTable reloadData];
});
}
-(void)f1
{
//load datas with a url request and update array1
}
-(void)f2
{
//load datas with a url request and update array2
}
-(void)f3
{
//load datas with a url request and update array3
}
但是在这里,我的tableView被“冻结”,直到它被刷新。
我不关心f1 f2和f3的执行顺序,但我需要等待刷新tableView之前完成这三个函数。
感谢您的帮助。
修改
感谢您的所有答案。
以下是工作解决方案:
正如mros的建议,我从viewDidLoad中删除了调度队列,并在reloadDatas中替换:
dispatch_queue_t concurrentQueue = dispatch_get_main_queue();
与
dispatch_queue_t mainThreadQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
最后,我在主线程中重新加载我的表
dispatch_async(dispatch_get_main_queue(), ^{ [myDisplayedTable reloadData]; });
答案 0 :(得分:5)
所以你的“后台线程”实际上就是你的主线程。您必须使用dispatch_get_global_queue并指定实际获得不同线程的优先级。此外,viewDidLoad中的dispatch async是无用的,因为在主线程中调用了所有视图控制器生命周期方法。我建议你在f1,f2和f3方法中做如下的事情:
首先启动异步URL请求,然后在完成块中更新arrayX并重新加载tableview的特定部分。这样,所有三个请求都可以同时发生,并且表只是在每个请求完成时更新必要的数据。或者,如果您只想重新加载一次,只需用后台线程替换concurrentQueue变量,然后在主线程上执行[tableView reloadData]
。
答案 1 :(得分:3)
之前的答案绝对正确。但是你执行reloadDatas& viewDidLoad有点问题。
只是为了澄清:
您希望在后台线程中完成耗时的数据加载,然后在主线程上准备好数据时更新UI / Cells。
像这样:
-(void)viewDidLoad
{
dispatch_queue_t concurrentQueue = dispatch_queue_create("com.my.backgroundQueue", NULL);
dispatch_async(concurrentQueue, ^{
[self reloadDatas];
});
}
-(void)reloadDatas
{
// Expensive operations i.e pull data from server and add it to NSArray or NSDictionary
[self f1];
[self f2];
[self f3];
// Operation done - now let's update our table cells on the main thread
dispatch_queue_t mainThreadQueue = dispatch_get_main_queue();
dispatch_async(mainThreadQueue, ^{
[myDisplayedTable reloadData]; // Update table UI
});
}
答案 2 :(得分:2)
在reloadDatas
方法中,您应该更改此行:
dispatch_queue_t concurrentQueue = dispatch_get_main_queue();
要:
dispatch_queue_t concurrentQueue = dispatch_queue_create("some queue", NULL);
但是当你打电话给[myDisplayedTable reloadData]
时,你需要在主队列中调用这个操作。
dispatch_async(dispatch_get_main_queue(), ^{ [myDisplayedTable reloadData]; });
答案 3 :(得分:1)
另一件事。从服务器中提取数据并更新表格单元格非常常见。 这里不需要队列或计时器。 这是另一种结构。
说你从你的服务器中拔出mp3: 您的模型类是:Music.h / m 你的模型管理器是:MusicManager.h / m(Singleton) - 它将包含一个音乐对象数组 - 单例基本上是你的数据源; 最后你的UItableViewController:MusicTableVC.h / m
在MusicManager.h / m中:您有 NSMutableArray ,它将加载您从服务器提取的Music.h对象。您可以在应用程序加载后立即执行此操作,甚至无需等待TableViewController。
在MusicManager中你有一些帮助方法来添加或删除mutableArray中的项目并提供计数,当然还有你的网络方法。
最后:在您的网络代码中发布通知。您的UITableViewController应该监听/观察该通知并重新加载"相应
[[NSNotificationCenter defaultCenter] postNotificationName:@"NewMusicAdded" object:nil];
您从服务器查询数据,将数据解析为音乐对象,将它们添加到NSMutable数组并发布通知以让表自行更新。
漂亮的标准食谱。