我遇到了一个奇怪的问题。我有一个Tab Bar应用程序,其中我正在为每个不同的选项卡使用导航控制器,每个导航控制器都有自己的View Controller来显示一些内容。
当我触摸选项卡时,我希望立即加载选项卡以及加载后(viewDidAppear:
)我希望它在viewDidAppear:方法中下载一些数据。
为了测试此功能,我设置了以下方法。我正在使用NSThread
来模拟执行一些冗长的操作,这应该在加载视图时在后台完成。然后我将NSArray *测试(非原子,保留)与一些测试数据分配并重新加载表。
我正在重新加载表,因为在viewDidLoad
方法中我将表设置为只包含一个空字符串(这是因为我读到该表是在调用viewDidAppear:之前设置的。
- (void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
DLog(@"viewDidAppear running");
[NSThread sleepForTimeInterval:10];
NSArray *array = [[NSArray alloc] initWithObjects:@"Test1", @"Test2", @"Test3", @"Test4", @"Test5", @"Test6", nil];
self.test = array;
[array release];
[table reloadData];
}
所以我的预期行为应该是,当触摸此特定选项卡时,它应立即加载 ,然后在10秒后,应使用viewDidAppear:方法中的表数据填充。 但的行为是触摸此标签时等待10秒,然后显示填充了表格数据的视图。
答案 0 :(得分:1)
调用[NSThread sleepForTimeInterval:10];
将阻止主线程进行任何更新,因此您无法看到任何用户界面更改。如果您想延迟重新加载表数据,请检查NSObject performSelector:withObject:afterDelay:
NSObject Class Reference
将reloadData和数组设置的代码放入方法中,并通过performSelector:withObject:afterDelay:
答案 1 :(得分:1)
其他答案解释了使用+[NSThread sleepForTimeInterval:]
方法时主线程被阻止的原因。
要处理从网上下载,您应该将下载任务推送到后台线程,以避免像在此处一样阻止主线程。您可以使用 Grand Central Dispatch 来实现此目的。
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, NULL), ^{
/* Download stuff */
dispatch_async(dispatch_get_main_queue(), ^{
/* Send UI updates back to the main thread. */
[self.tableView reloadData];
});
});
答案 2 :(得分:0)
你是不是把错误的线程睡了? (即将创建数组的那个)
好像你等了10秒然后再调用表reloadData。
你为什么还在等?一旦数据可用,您不希望填充tableView吗?
答案 3 :(得分:0)
-(void)executeMe{
NSArray *array = [[NSArray alloc] initWithObjects:@"Test1", @"Test2", @"Test3", @"Test4", @"Test5", @"Test6", nil];
self.test = array;
[array release];
[table reloadData];
}
- (void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
DLog(@"viewDidAppear running");
[self performSelector:@selector(executeMe) withObject:nil afterDelay:10];
}