Sure, I agree it could be done and, assuming it was done, that the sequential behavior of the newly-async viewWillAppear will be just fine.
The issue that I think you're not addressing is that viewWillAppear is stateful. It is a view controller state that exists between the call and the return. In order to associate the behavior with the state, you need to know when the return happens — not when the body of the function finishes executing.
For example, here is something that is meaningful today:
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
if someCondition {
doSynchronousStuff()
self.needsCleanup = true
}
}
override func viewDidAppear(_ animated: Bool) async {
super.viewDidAppear(animated)
if self.needsCleanup {
doCleanupStuff()
self.needsCleanup = false
}
}
It makes sense to begin some setup in viewWillAppear and finish it in viewDidAppear. Compare with an async variant:
override func viewWillAppear(_ animated: Bool) async {
super.viewWillAppear(animated)
if someCondition {
await doAsynchronousStuff()
self.needsCleanup = true
}
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
if self.needsCleanup {
doCleanupStuff()
self.needsCleanup = false
}
}
Note that we didn't change the sequencing of what viewWillAppear does. It still happens in the right order. However, self.needsCleanup = true is now effectively detached (well, may be detached, depending on whether suspension actually occurs), and that makes it incorrect to test it in viewDidAppear.
The point I was trying to make in my earlier post was that, when we know from the source code where viewWillAppear will actually return to its caller, we can reason about viewDidAppear and other things that happen "next". We lose that ability if viewWillAppear is suddenly async.
That example may be too simple to be convincing, but it shows the general principle. We might, for example, have:
override func viewWillAppear(_ animated: Bool) {
if someCondition {
doSynchronousStuff()
self.needsCleanup = true
super.viewWillAppear(animated)
}
else {
super.viewWillAppear(animated)
doAlternateSynchronousStuff()
}
(That is, we may want to call super at the end of the function sometimes.) You can't safely make this function async just by changing the synchronous stuff into awaited asynchronous stuff.
Again, this is not about sequencing the body of the function. It's about the relationship of the body of the function to the caller.