问题
First of all I'd like to say sorry in case you consider my question dummy, I'm new to iOS and multithreading and just want to understand how things are going on. As far as I know didEnterBackground
is the last function that iOS calls before app suspension and the app has about 5 secs to return from it otherwise iOS will kill the app. I'm currently thinking about such a situation - I have some task that is happening on the background thread(e.g. network download) and its completion block happens on the main thread. like this
fun downloadData() {
Downloader.download(url: "someUrl") { [weak self] in // download is on the background thread
DispatchQueue.main.async { [weak self] in // switch to main
// do some stuff
}
}
}
downloadData()
is currently running on the background thread, the user taps on the home button and the app goes to background and didEnterBackground
is called. While main thread executes code in didEnterBackground
downloadData
finishes downloading and its completion is called and the new task is pushed into main threads queue. So what would happen in this case? Since the code from didEnterBackground
is the last that can be execute before the suspension what would happen to the completion block of downloadData
, would it also be executed before the suspension(after didEnterBackground
) or it would be executed once the user will return to the app, or it will be discarded? Or this situation is not possible at all ? Thank you for your help and again sorry if my question is incorrect.
回答1:
First of all, I suggest you consider this document provided Apple. The document is clear by itself, but I'll go through it to extract important information that matches your question.
In this document, apple says explicitly that every suspended UI task will be discarded and you should not submit new tasks to Dispatch queues and you should suspend the current queues and release resources ASAP.
When app is supposed to be deactivated, There are two steps:
- System calls application
applicationWillResignActive(_:)
method (orsceneWillResignActive(_:)
If your usingsceneDelegate
) - Then UIKit calls
applicationDidEnterBackground(_:)
method (orsceneDidEnterBackground(_:)
)
In the first step, UIKit is notifying you about deactivation, which implies that after a few times later, the app will enter in background. While this step, you must save all the sensitive data.
During this step, if you have suspended UI tasks, All of them will be discarded.
The system also deactivates apps when it needs to interrupt them temporarily—for example, to display system alerts
During this step, you must pause your running task, As Apple says, You should make your app quiet
Save user data to disk and close any open files.
Suspend dispatch and operation queues.
Don’t schedule any new tasks for execution.
Invalidate any active timers.
Pause gameplay automatically.
...
In the Second steps when UIKit notifies your app about transferring tp background state, You must free shared resources as quickly as possible, If you persist to use the resources your app will be terminated.
So the mentioned UI task in your question will be discarded.
I also recommend studying this document about app states which helps with understanding application state.
来源:https://stackoverflow.com/questions/61689438/is-it-possible-to-execute-something-on-main-thread-after-didenterbackground-is-c