请原谅我不知道这一点,但我想知道为什么当我尝试与数据库建立连接时会出现延迟。
我基本上从数据库中提取数据以将信息显示回UITableView
,但似乎连接建立有延迟。
- (void)viewDidLoad
{
[super viewDidLoad];
[self fetchFromDatabase];
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
[self fetchFromDatabase];
NSLog(@"FOUR");
}
- (void)fetchFromDatabase
{
// The URL of the database
NSURL *url = [[NSURL alloc] initWithString:SDTET_DATABASE_SCHEDULE];
// Establish the connection to the database
[NSURLConnection sendAsynchronousRequest:[ [NSURLRequest alloc] initWithURL:url] queue:[ [NSOperationQueue alloc] init] completionHandler:^(NSURLResponse *response, NSData *data, NSError *error)
{
NSLog(@"ONE !");
} ];
}
然而,输出看起来像这样:
FOUR
FOUR
ONE!
为什么没有ONE !
首先打印出来?
如果可能,如何在调用numberOfSections之前确保连接发生?
由于
答案 0 :(得分:3)
ONE最后打印,因为您正在调用异步方法。
您可以按照程序的流程(哪种方法以何种顺序调用)。如果我们让想象力有所延伸,我们可以说当一个方法同步时,它基本上“说”到下一行代码等待它(方法)完成。 但是,如果方法是异步的,它会说“不要等我”。您使用的URL请求方法是异步的。这意味着它开始完成它的工作但没有人等待,代码的执行在下一行立即继续。
谜题中有一块可以更清楚地说明这一点。请求方法需要以完成块作为参数。解释块在这里超出了范围,但是您需要了解什么块才能完全掌握问题的解决方案。 可以这么说,一旦这个异步方法完成它的工作(这可能是很长时间而且这个真的是异步方法的原因之一),就会调用并执行该块。
因此,要回答上一个问题,您需要在表视图上触发刷新,这是通过调用实现的
块内[self.tableView reloadData];
。这里有一个很好的逻辑,因为你知道只有在异步方法结束它的工作后才执行该块,你将刷新你的表视图,知道你有来自db的更新数据。
答案 1 :(得分:1)
这是因为它是一个异步请求(意味着它不一定立即发生)。这是计算机科学的一个重要原则,它比Objective-C或iOS开发更大的概念。
在您的情况下,您可以摆脱numberOfSectionsInTableView:
中调用的抓取工作,然后只需拨打[self.tableView reloadData]
中的completionHandler
。
答案 2 :(得分:1)
由于网络访问速度缓慢,因此存在延迟。有时候它真的很慢。
有时您可以在不到一秒的时间内得到回复,有时可能需要一分钟的时间来获得回复。
您应始终将网络代码编写为异步,这意味着您使用立即返回的方法提交请求。您的程序继续运行,然后在收到响应后收到通知。
您的代码发生了什么。
您不希望在numberOfSectionsInTableView中发送加载数据的请求。您应该尽早发送网络请求,最好是在显示结果的视图控制器显示之前。
但是,在填充数据之前显示表视图是很常见的。您可能会显示一个空表视图,其中包含数据正在加载的消息,或者带有进度对话框。在其他情况下,您可能知道要显示多少个单元格,并且具有文本数据但不包含图像。在这种情况下,您可以使用占位符图像填充单元格。加载数据后,您可以更新显示。
在您的情况下,您应该编写numberOfSectionsInTableView和numberOfRowsInSection:
方法以返回零,然后使网络调用的完成方法告诉表视图重新加载。