【发布时间】:2020-02-04 04:03:15
【问题描述】:
简而言之,我试图在 WEB 上显示来自公开可用 JSON 文件的数据。流程如下:
我使用NSURLSessionDataTask 启动下载,然后解析并显示 JSON 或处理错误(如果发生)。这是我的相关代码:
- (void) initiateDownload {
NSURLSessionConfiguration *sessionConfig = [NSURLSessionConfiguration defaultSessionConfiguration];
sessionConfig.timeoutIntervalForRequest = 5.0f;
sessionConfig.timeoutIntervalForResource = 20.0f;
NSURLSessionDataTask *downloadWeatherTask = [urlSession dataTaskWithRequest:urlRequest
completionHandler:^(NSData *data, NSURLResponse *response, NSError *downloadError) {
if (downloadError) {
dispatch_sync(dispatch_get_main_queue(), ^{
[self errorReceived:downloadError];
});
} else if (data) {
dispatch_sync(dispatch_get_main_queue(), ^{
[self parseWeatherJSON:data];
});
}
}];
[downloadWeatherTask resume];
}
我对此有几个问题:
-
我对线程处理不是很熟悉。虽然我添加了
dispatch_sync(dispatch_get_main_queue(), ...)到两个完成块,它似乎工作,我不确定这是线程安全的最佳方式(之前,我收到各种错误消息并在下载完成后显示数据需要 10 秒)。有没有更好的方法来处理下载,线程或我的是可接受的解决方案?
-
我希望用户能够在他/她想要刷新显示的数据的任何时候手动启动下载过程。起初,我将
NSURLSessionDataTask初始化一次,并使其在课堂上的任何地方都可用;所以我可以在每次调用刷新时调用 resume。但是,我找不到重新执行下载过程的命令。一旦我打电话给[downloadWeatherTask resume],我就无法从头开始任务。所以,我将任务添加到一个单独的函数(您在上面看到的那个),并在每次调用该函数时对其进行初始化。这很好用,但我不确定这是最好的方法。例如,它是内存安全的,还是我每次用户发起刷新调用时都创建一个新任务并最终耗尽内存?
感谢您的回答!
更多信息:我使用最新的 XCode 11 并针对 iOS 9 及更高版本。
【问题讨论】:
-
如果你原谅了不相关的观察,但你正在创建一个
NSURLSessionConfiguration,但你没有使用它。配置应在NSURLSession的实例化期间创建和使用。而且您不想在每次执行此请求时都这样做,因此请将此NSURLSessionConfiguration代码从此例程中拉出,并将其放在您实例化urlSession的任何位置。 -
另外,一个非常小的观察,但是您使用“下载任务”的术语来指代您的
NSURLSessionDataTask。实际上有一个名为NSURLSessionDownloadTask的对象类型,用于下载到文件。您可以考虑为您在此处所做的工作采用“数据任务”这一术语,以避免将来出现混淆。 -
"如果你原谅了不相关的观察,但你正在创建一个 NSURLSessionConfiguration,但你没有使用它。"谢谢你指出。我的印象是它是全球性的,并且普遍适用于所有 url 会话。那么,我如何使它在这种情况下正常工作?如果我只是将它移动到我的 init 会发生什么(那是我初始化我的 url 会话的地方)。
-
不,这不是全球性的。无论您定义
urlSession,您都可以使用use this configuration,例如urlSession = [NSURLSession sessionWithConfiguration:sessionConfig];。但请确保在init中执行此操作,因此您只创建一次会话。每个NSURLSession都有开销。 -
谢谢 Rob,这很有道理。
标签: objective-c ios9 nsurlsession ios13 xcode11