为什么使用 NSURLConnection sendAsynchronousRequest 建立与数据库的连接会延迟?
Why is there a delayed in establishing a connection to a database using NSURLConnection sendAsynchronousRequest?
对不起,我不知道这个,但我想知道为什么我尝试建立与数据库的连接时会出现延迟。
我基本上是从数据库中提取数据以将信息显示回 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 之前发生连接?
谢谢
这是因为它是一个异步请求(意味着它不一定立即发生)。这是计算机科学的一个重要原则,它是一个比 Objective-C 或 iOS 开发更大的概念。
在您的情况下,您可以摆脱在 numberOfSectionsInTableView:
中调用的提取,而只需在 completionHandler
中调用 [self.tableView reloadData]
。
因为网络访问速度慢,所以有延迟。有时真的很慢。
有时您可以在不到一秒的时间内收到回复,而有时您可能需要一分钟的大部分时间才能收到回复。
您应该始终将您的网络代码编写为异步的,这意味着您使用 return 立即提交请求的方法。您的程序继续 运行,然后在收到响应后您会收到通知。
您的代码就是这样。
您不想发送在 numberOfSectionsInTableView 中加载数据的请求。您应该尽早发送网络请求,最好在显示结果的视图控制器显示之前发送。
但是,在您有数据填充之前显示 table 视图是很常见的。您可能会显示一个空的 table 视图,其中包含数据正在加载的消息或进度对话框。在其他情况下,您可能知道要显示多少个单元格,并且有文本数据但没有图像。在这种情况下,您可以使用占位符图像填充您的单元格。加载数据后,您可以更新显示。
在您的情况下,您应该将 numberOfSectionsInTableView 和 numberOfRowsInSection:
方法写入 return 零,然后使网络调用的完成方法告诉 table 视图重新加载自身。
ONE 最后打印,因为您正在调用异步方法。
您可以按照程序的流程进行操作(哪个方法按什么顺序调用哪个)。如果我们想象一下,我们可以说当一个方法是同步的时候,它基本上"says"到下一行代码等待它(方法)完成。
但是,如果一个方法是异步的,它会说 "don't wait for me"。您使用的 URL 请求方法是异步的。这意味着它开始做它的工作但没有人等待,代码的执行在下一行立即。
拼图中有一块可以进一步阐明这一点。请求方法需要提供一个 完成块 作为参数。解释块超出了此处的范围,但您需要了解块是什么才能完全掌握问题的解决方案。
可以这么说,一旦这个异步方法完成它的工作(这可能会很长时间,this 确实是异步方法的原因之一),该块将被调用并执行。
因此,要回答您的最后一个问题,您需要触发 table 视图的刷新,您可以通过调用
[self.tableView reloadData];
在 街区内。这里有一个很好的逻辑,因为您知道块仅在异步方法完成其工作后才执行,您将刷新 table 视图,知道您有来自 db 的更新数据。
对不起,我不知道这个,但我想知道为什么我尝试建立与数据库的连接时会出现延迟。
我基本上是从数据库中提取数据以将信息显示回 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 之前发生连接?
谢谢
这是因为它是一个异步请求(意味着它不一定立即发生)。这是计算机科学的一个重要原则,它是一个比 Objective-C 或 iOS 开发更大的概念。
在您的情况下,您可以摆脱在 numberOfSectionsInTableView:
中调用的提取,而只需在 completionHandler
中调用 [self.tableView reloadData]
。
因为网络访问速度慢,所以有延迟。有时真的很慢。
有时您可以在不到一秒的时间内收到回复,而有时您可能需要一分钟的大部分时间才能收到回复。
您应该始终将您的网络代码编写为异步的,这意味着您使用 return 立即提交请求的方法。您的程序继续 运行,然后在收到响应后您会收到通知。
您的代码就是这样。
您不想发送在 numberOfSectionsInTableView 中加载数据的请求。您应该尽早发送网络请求,最好在显示结果的视图控制器显示之前发送。
但是,在您有数据填充之前显示 table 视图是很常见的。您可能会显示一个空的 table 视图,其中包含数据正在加载的消息或进度对话框。在其他情况下,您可能知道要显示多少个单元格,并且有文本数据但没有图像。在这种情况下,您可以使用占位符图像填充您的单元格。加载数据后,您可以更新显示。
在您的情况下,您应该将 numberOfSectionsInTableView 和 numberOfRowsInSection:
方法写入 return 零,然后使网络调用的完成方法告诉 table 视图重新加载自身。
ONE 最后打印,因为您正在调用异步方法。
您可以按照程序的流程进行操作(哪个方法按什么顺序调用哪个)。如果我们想象一下,我们可以说当一个方法是同步的时候,它基本上"says"到下一行代码等待它(方法)完成。 但是,如果一个方法是异步的,它会说 "don't wait for me"。您使用的 URL 请求方法是异步的。这意味着它开始做它的工作但没有人等待,代码的执行在下一行立即。
拼图中有一块可以进一步阐明这一点。请求方法需要提供一个 完成块 作为参数。解释块超出了此处的范围,但您需要了解块是什么才能完全掌握问题的解决方案。
可以这么说,一旦这个异步方法完成它的工作(这可能会很长时间,this 确实是异步方法的原因之一),该块将被调用并执行。
因此,要回答您的最后一个问题,您需要触发 table 视图的刷新,您可以通过调用
[self.tableView reloadData];
在 街区内。这里有一个很好的逻辑,因为您知道块仅在异步方法完成其工作后才执行,您将刷新 table 视图,知道您有来自 db 的更新数据。