问题
This is the scenario:
- NSURLSession with background Configuration
- Download or upload task start with Bad or No Internet Connection.
- User close the App.
- If iOS get Internet Connection will star session task. However,
- With task still waiting for Internet.
- User kills the App
- System cancel all pending tasks
The Question
It is possible to know when the user opens the app again that the tasks were cancelled?
If yes, where?
This Answer says yes, it is possible, but I can not get any callback returning me an error.
I'm using Alamofire to handle all my Networking calls. However, I doubt that Alamofire will change the behavior.
Edit 1
/// Networking manager with Background Session Configuration
static var backgroundManager: Alamofire.Manager = {
let configuration = NSURLSessionConfiguration.backgroundSessionConfigurationWithIdentifier("com.xxx.NetworkingManager.Identifier")
configuration.HTTPAdditionalHeaders = Manager.defaultHTTPHeaders
let backgroundManager = Alamofire.Manager(configuration: configuration)
return backgroundManager
}()
回答1:
Kudos to Rob because he showed me the right path.
So after the user kills the app, the system cancels all the pending tasks.
You can see that with the system.log:
Simulator/Debug/Open System Log...
How to catch what was already ongoing?
Instantiate again your Background NSURLSession
. Do it elsewhere, but I'll do it in AppDelegate for this example.
The system knows (thanks to the identifier) that it is the same Background Session that before so it maps the pending tasks.
Then retrieve all the tasks. The canceled tasks are still there
The tasks will have a error that you can check.
Error Domain=NSURLErrorDomain Code=-999 "(null)"
UserInfo={NSErrorFailingURLStringKey=http://your.api.com/url,
NSURLErrorBackgroundTaskCancelledReasonKey=0,
NSErrorFailingURLKey=http://your.api.com/url}
Also, with the tasks, you will get the Request URL, so you can map your app requests and do something.
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
// This is the code for Swift 2.x. In Swift 3.x this call is a bit different.
NetworkingManager.backgroundManager.session.getTasksWithCompletionHandler { (data, upload, download) in
for task in data {
NSLog("\(task.error)")
}
for task in upload {
NSLog("\(task.error)")
}
for task in download {
NSLog("\(task.error)")
let reason = task.error?.userInfo[NSURLErrorBackgroundTaskCancelledReasonKey] as? Int
let code = task.error?.code
if reason == NSURLErrorCancelledReasonUserForceQuitApplication &&
code == NSURLErrorCancelled {
NSLog("\(task.originalRequest)")
NSLog("\(task.currentRequest?.URL)")
}
}
}
}
NSURLErrorCancelledReasonUserForceQuitApplication
-> The operation was canceled because the user forced the app to quit.
So we are on the right track. If someone has a better solution, please share! I do not really like the mapping solution of my requests urls.
来源:https://stackoverflow.com/questions/40613525/nsurlsession-with-background-configuration-and-app-killed-by-user