iOS-在应用程序关闭的情况下在后台运行网络请求

iOS-在应用程序关闭的情况下在后台运行网络请求,ios,objective-c,swift,network-programming,taskscheduler,Ios,Objective C,Swift,Network Programming,Taskscheduler,您好,我目前正在开发一个跨平台(本机Java和Swift/Objective-C)移动应用程序,用户可能经常无法访问网络连接,但我们希望在网络可用时记录并发送统计数据,即使我们的应用程序已关闭。我们已经通过Android上的AndroidX.WorkManager库很容易做到这一点,如下所示: stringurl=”https://myexampleurl.com"; 数据输入数据=新数据.Builder() .putString(“URL”,URL) .build(); Constraints

您好,我目前正在开发一个跨平台(本机Java和Swift/Objective-C)移动应用程序,用户可能经常无法访问网络连接,但我们希望在网络可用时记录并发送统计数据,即使我们的应用程序已关闭。我们已经通过Android上的
AndroidX.WorkManager
库很容易做到这一点,如下所示:

stringurl=”https://myexampleurl.com";
数据输入数据=新数据.Builder()
.putString(“URL”,URL)
.build();
Constraints Constraints=new Constraints.Builder().setRequiredNetworkType(NetworkType.CONNECTED).build();
OneTimeWorkRequest workRequest=新建OneTimeWorkRequest.Builder(NetworkWorker.class)
.setInputData(inputData)
.setConstraints(约束)
.build();
WorkManager.getInstance(context.enqueueUniqueWork(“com.lkuich.exampleWorker”,ExistingWorkPolicy.APPEND\u或\u REPLACE,workRequest);
这非常有效,当我们的应用程序调用此方法时,我们的请求被添加到队列中,即使用户脱机并关闭我们的应用程序,当他们重新连接到网络时,我们的请求仍然会被发出

然而,我一直在努力寻找与此API相当的iOS,我对本机iOS开发还相当陌生。我们已经在项目中启用了后台任务功能并在
Plist.info
中注册了标识符

首先,我们尝试了
URLSession
“后台”API,如下所示:

类网络控制器:NSObject,URLSessionTaskDelegate{
func buildTask()->URLSession{
让config=URLSessionConfiguration.background(标识符为:“com.lkuich.exampleWorker”)
config.waitsForConnectivity=true
config.shouldUseExtendedBackgroundIdleMode=true
返回URLSession(配置:config,委托:self,委托队列:OperationQueue.main)
}
func makeNetworkRequest(会话:URLSession){
让url=url(字符串:https://myexampleurl.com")!
let task=session.dataTask(带:url)
task.resume()
}
func urlSession(uSession:urlSession,task:URLSessionTask,DidCompleteWither错误:错误?){
打印(“我们在这里完成了”)
}
}
当WiFi被禁用并重新启用时,这项功能运行良好,但如果应用程序关闭,请求似乎永远不会发送

因此,我们尝试了
BGTaskScheduler
,但我很难测试它是否在后台运行,并且应用程序关闭,因为它通常需要几个小时才能实际运行(通过网络连接强制它立即运行):

static let bgIdentifier=“com.lkuich.exampleWorker”
//在应用程序启动时调用(didFinishLaunchingWithOptions)
静态函数注册表BackgroundTasks(){
BGTaskScheduler.shared.register(forTaskWithIdentifier:bgIdentifier,using:nil){(task)in
task.expirationHandler={
task.setTaskCompleted(成功:false)
}
//在BG中发出网络请求
让url=url(字符串:https://myexampleworker.com")!
让t=URLSession.shared.dataTask(带有:url,completionHandler:{data,response,error in
//打印响应
打印(答复)
task.setTaskCompleted(成功:true)
})
t、 简历()
}
}
静态func makeRequest(){
做{
让bgRequest=BGProcessingTaskRequest(标识符:bgIdentifier)
bgRequest.requiresNetworkConnectivity=true
bgRequest.requiresExternalPower=false
尝试BGTaskScheduler.shared.submit(bgRequest)
打印(“提交的任务请求”)
}抓住{
打印(“提交任务失败”)
}
}
所以总的来说,我的问题是,当网络可用时,即使调用的应用程序关闭,是否可以安排在后台运行网络请求?如果是这样,我将如何将输入数据(例如URL参数)传递给我的后台任务,因为我的任务必须在应用程序启动时注册


谢谢你,Loren K

一个关闭的应用程序可能处于两种状态。它要么在背景中,要么被杀死。应用程序可以由系统出于各种原因而终止,也可以由用户通过应用程序切换器终止

这很重要,因为当应用程序被终止时,你不能在后台做任何事情。只有VoIP应用程序例外(使用PushKit,如果应用程序没有VoIP功能,您将无法通过AppStore,您现在可以使用该应用程序)和watchOS。但对于所有其他应用程序,当应用程序被杀死时,你没有任何选择。这只是苹果的标准,他们不希望那些没有运行的应用程序能够出于安全原因运行代码

当应用程序仍在后台时,您可以使用您提到的BGTaskAPI注册一些要完成的任务。我在我的一个应用程序中使用了相同的API,发现它非常不稳定。有时一项任务每30分钟完成一次,然后直到明天早上才执行,然后有时它会完全停止执行


因此,我认为静默推送通知是最好的解决方法,但它们也只有在应用程序仍在后台时才起作用,而不是死机。除非您的应用程序具有VoIP功能,否则您可以使用PushKit。

关闭的应用程序可能处于两种状态。它要么在背景中,要么被杀死。应用程序可以由系统出于各种原因而终止,也可以由用户通过应用程序切换器终止

这很重要,因为当应用程序被终止时,你不能在后台做任何事情。只有VoIP应用程序例外(使用PushKit,如果