离线时在iOS上进行http调用

时间:2014-08-16 20:52:00

标签: ios http afnetworking nsoperationqueue

也许我一直在阅读错误的东西,但有一点我所阅读的所有文献似乎都认同:iOS不允许后台线程运行超过十分钟。这似乎违反了应用程序开发的最大原则之一:用户应该看不到互联网。所以这是一个场景。

用户正在通过隧道或在飞机上飞行,这不会导致网络不可靠或不可靠。在那一刻,用户拿出我的电子邮件应用程序,撰写电子邮件,然后点击发送按钮。

问题:开发人员如何确保在网络可用时发送电子邮件?当然我使用电子邮件作为一般示例,但实际上我正在处理一个非常简单的http情况,我的应用程序需要向我的服务器发送POST。

Side Note :在Android上,我使用Path的优先级作业队列,这允许我设置它并忘记它(即一旦有网络发送我的电子邮件)。

另一个侧面注释:我一直在尝试将NSOperationQueue与AFNetworking一起使用,但不会这样做。

4 个答案:

答案 0 :(得分:1)

您可以使用背景NSURLSession完成您想要实现的目标。虽然AFNetworking基于NSURLSession,但我不太确定它是否可以与您的应用程序不运行的后台会话一起使用。但是你真的不需要这个,NSURLSession很容易使用。

作为第一步,您需要为后台会话创建会话配置:

let config = URLSessionConfiguration.background(withIdentifier: "de.5sw.test")
config.isDiscretionary = true
config.waitsForConnectivity = true

isDiscretionary属性允许系统决定何时执行数据传输。 waitsForConnectivity(自iOS 11起可用)使系统等待,如果没有互联网连接而不是立即失败。

使用该配置对象,您可以创建URL会话。重要的是指定一个委托,因为当应用程序终止时,基于闭包的回调会丢失。

let session = URLSession(configuration: config, delegate: self, delegateQueue: OperationQueue.main)

要执行上传,您要求会话创建上传任务,然后重新开始。对于上传任务,首先要创建URLRequest,指定URL和所有需要的标题。您要上传的实际数据需要写入文件。如果您将其作为Data或流对象提供,则在您的应用终止后无法上传。

let task = session.uploadTask(with: request, fromFile: fileUrl)
task.resume()

要获得上传成功或失败的通知,您需要实施URLSessionDataDelegate方法urlSession(_:task:didCompleteWithError:)。如果错误为nil,则转移成功。

缺少的最后一件事是处理您的应用未运行时发生的事件。为此,您需要在应用委托中实施方法application(_:handleEventsForBackgroundURLSession:completionHandler:)。当系统决定您需要处理某些事件以进行后台传输时,它会在后台启动您的应用并调用此方法。

在那里,您需要先存储完成处理程序,然后使用之前使用的相同配置重新创建URLSession。然后,它会像往常一样调用它需要处理的事件的委托。完成事件后,它会调用委托方法urlSessionDidFinishEvents(forBackgroundURLSession:)。从那里你需要调用传递给你的app delegate的完成处理程序。

会话配置提供了更多选项:

  • timeoutIntervalForResource:系统应尝试执行上传多长时间。默认为7天。
  • sessionSendsLaunchEvents:如果false该应用将无法启动以处理事件。当用户手动打开应用程序时,将处理它们。默认值为true

这是一个小型示例项目,展示了所有内容如何组合在一起:https://github.com/5sw/BackgroundUploadDemo

答案 1 :(得分:0)

您的应用需要在内部存储数据,然后您需要一些会导致应用在后台运行的内容(但如果您没有理由这样做,则不一定要添加一些内容)或等到用户下次将应用程序带到前台 - 然后您可以检查网络连接并拨打电话。

请注意,电子邮件与POST非常不同,因为您可以将电子邮件传递给系统邮件应用程序以便为您发送,但是您无法使用POST执行完全相同的操作。

如果可以使用它,请考虑查看NSURLSessionUploadTask

答案 2 :(得分:0)

用三个词说:你没有。

这实际上是一件好事。 当然不想思考和推测我的最后20个应用程序,如果它们仍然在后台运行,使用内存,电池和带宽。此外,如果需要更多内存,它们将被杀死。用户如何能够预测它是否成功完成任务?他不能,并且无论如何都需要打开应用程序来检查。

至于电子邮件示例,我会将电子邮件显示为“待处理”(即未发送),直到它正确传输为止。让用户明白他必须稍后回来完成这项工作。

虽然每个开发人员都认为他的应用程序具有非常好的背景原因,但实际情况是,对于99%的用户而言,这只是一种痛苦。你能说“任务经理”吗? ; - )

答案 3 :(得分:0)

我写了一个可以做到这一点的吊舱 - https://cocoapods.org/pods/OfflineRequestManager。如果要监视请求是处于挂起还是已完成/失败状态,则必须执行一些监听委托回调的工作,但我们一直在使用它来确保请求在较差或无连接情况下发出。

最简单的用例看起来如下所示,尽管大多数实际情况(保存到磁盘,特定请求数据等)都会有更多的环节要跳过:

import OfflineRequestManager

class SimpleRequest: OfflineRequest {
    func perform(completion: @escaping (Error?) -> Void) {
        doMyNetworkRequest(withCompletion: { response, error in
            handleResponse(response)
            completion(error)
        })
    }
}
///////
OfflineRequestManager.defaultManager(queueRequest: SimpleRequest())