当用户终止应用程序时,我可以进行 api 调用吗?
Posted
技术标签:
【中文标题】当用户终止应用程序时,我可以进行 api 调用吗?【英文标题】:Can I make an api call when the user terminates the app? 【发布时间】:2019-03-19 06:31:22 【问题描述】:当用户终止应用程序(强制关闭)时,我需要进行 API 调用。我所做的直接实现如下。
在应用委托中,我添加了以下代码。
func applicationWillTerminate(_ application: UIApplication)
print("________TERMINATED___________")
testAPICall()
func testAPICall()
let url = getURL()
let contentHeader = ["Content-Type": "application/json"]
Alamofire.request(url,
method: .put,
parameters: ["username": "abc@xyz.com"],
encoding: JSONEncoding.default,
headers: contentHeader).responseJSON (response) -> Void in
print("-----")
但是,没有进行呼叫。在通过documentation 时,我发现在此方法中完成任务只有 5 秒,最重要的是,调用 api 不是在这里完成的任务。所以我想知道,这样做的方法是什么。
【问题讨论】:
检查这个-hackingwithswift.com/example-code/system/… 要不要等回复,就不能“开枪就忘了”吗? 您可以在应用程序终止时在用户默认值中保留一个标志,并在用户返回时通过检查标志调用didBecomeActive
中的API。
@Joakim Danielson 我不需要等待响应,但没有触发 api 调用。我有解决办法。谢谢。
@Ankit Jayaswal 我需要在用户终止时拨打电话。我可以使用下面的解决方案来做到这一点。谢谢。
【参考方案1】:
这是一个双重问题
第 1 阶段:确保每次用户终止应用/在激活之前启动 API 调用
您始终可以在您的 appdelegate 中使用ios application
的expiration handler
后台模式
声明
var bgTask: UIBackgroundTaskIdentifier = UIBackgroundTaskIdentifier(rawValue: 0);
在你的 appdelegate 中
func applicationDidEnterBackground(_ application: UIApplication)
// Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
// If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
bgTask = application.beginBackgroundTask(withName:"MyBackgroundTask", expirationHandler: () -> Void in
// Do something to stop our background task or the app will be killed
application.endBackgroundTask(self.bgTask)
self.bgTask = UIBackgroundTaskIdentifier.invalid
)
DispatchQueue.global(qos: .background).async
//make your API call here
// Perform your background task here
print("The task has started")
后台过期处理程序将确保您每次将应用程序变为非活动或终止时都有足够的时间来启动 API 调用
第 2 阶段:确保 API 调用成功完成
虽然过期处理程序可能确保您有足够的时间启动 API 调用,但它不能确保 API 调用的成功完成。如果 API 调用需要更长的时间并且在请求进行中并且时间用完时怎么办?
确保 API 调用在启动后成功的唯一方法是确保为 URLSession
使用正确的配置
根据文档
后台会话可让您执行内容的上传和下载 在您的应用未运行时在后台运行。
链接:https://developer.apple.com/documentation/foundation/nsurlsession?language=objc
所以利用后台会话并使用上传任务。与其拥有一个普通的 get/post API,您将使用一些参数,请您的后端开发人员接受一个文件并将您的所有参数数据放入该文件(如果有的话)并使用后台会话启动上传任务。
一旦上传任务从后台会话开始,即使在您的应用被终止后,iOS 也会处理它的完成(除非您显然面临身份验证挑战)。
我相信这是确保启动 API 调用并确保在应用程序处于非活动/终止状态后完成的最接近方法。我与苹果开发人员讨论过同样的问题,他们同意这可能是一个可能的解决方案:)
希望对你有帮助
【讨论】:
@sujal:嘿 sujal 抱歉,我在深夜看到你的评论,因为我的带宽足以解决你的文件上传问题。感谢您接受答案 :) 欣赏它 :) 我不再在这里看到您的评论,我相信您的问题现在已经解决了,如果您仍然面临问题,请让我知道 :) 欢呼快乐编码 嗨@Sujal 和sandeep,我也想在应用程序终止时调用api,但无法发送文件。在这种情况下,最好的解决方案是什么? 嗨 @SandeepBhandari 在最新的 Xcode 中,我们有场景委托,那么我们如何在 sceneDidEnterBackground 方法中处理这个事情?【参考方案2】:这里的主要思想是在应用终止之前进行同步调用
func applicationWillTerminate(_ application: UIApplication)
let semaphore: dispatch_semaphore_t = dispatch_semaphore_create(0)
let request = NSMutableURLRequest(URL:url)
let task = NSURLSession.sharedSession().dataTaskWithRequest(request,
completionHandler:
taskData, _, error -> () in
dispatch_semaphore_signal(semaphore);
)
task.resume()
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER)
提示:
调度信号量是传统计数信号量的有效实现。仅当调用线程需要被阻塞时,调度信号量才会向下调用内核。如果调用信号量不需要阻塞,则不进行内核调用。
您可以通过调用 signal() 方法来增加信号量计数,并通过调用 wait() 或其指定超时的变体之一来减少信号量计数。
【讨论】:
虽然此代码可能会回答问题,但提供有关此代码为何和/或如何回答问题的额外上下文可提高其长期价值。【参考方案3】:这是完成此任务的简单方法-
func applicationWillTerminate(_ application: UIApplication)
let sem = DispatchSemaphore(value: 0)
startSomethingAsync(completionHandler:
sem.signal()//When task complete then signal will call
)
sem.wait()//waiting until task complete
【讨论】:
以上是关于当用户终止应用程序时,我可以进行 api 调用吗?的主要内容,如果未能解决你的问题,请参考以下文章
当我们进行API调用时,Docusign会保留发送文档的副本吗 - eSignRestAPI?
当应用程序在objective.c中终止时,我可以处理“静默通知”吗? [关闭]
Angular 5 - 当用户关闭浏览器窗口时如何进行 API 调用?