There is a subtle change in the latest template update. The variables viewController
, interactor
, and presenter
are now declared as real optionals using ?
. (They were forced unwrapped optionals with !
before.)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
class CreateOrderViewController: CreateOrderDisplayLogic { var interactor: CreateOrderBusinessLogic? } class CreateOrderInteractor: CreateOrderBusinessLogic { var presenter: CreateOrderPresentationLogic? } class CreateOrderPresenter: CreateOrderPresentationLogic { var viewController: CreateOrderDisplayLogic? } |
Why?
There was a situation where it could cause a crash if presenter
is deallocated and a method is invoked on it.
This happens when the interactor does some asynchronous work. Before it can finish, the user has navigated away (such as tapping the back button) from the current scene.
Because the view is no longer needed, UIKit does the right thing to purge the view controller from memory. This frees up the memory for other tasks.
As a result, the whole VIP cycle is taken down as well. The view controller, interactor, and presenter are removed from memory.
This is all good and is the intended behavior. But it also means that when the result does come back from the asynchronous call, there’s no presenter to invoke.
self.presenter.presentFetchedOrders(response: response)
causes a crash.
This was a nasty little bug that scratched some heads.
An obvious fix was to just check to see if presenter
is nil before invoking it:
1 2 3 4 |
if let _ = self.presenter { self.presenter.presentFetchedOrders(response: response) } |
But that’s ugly.
With the new change using real optionals, we can take advantage of Swift’s built-in nil check:
1 2 |
self.presenter?.presentFetchedOrders(response: response) |
Best of all, Xcode autocompletes the ?
for you.
Simple. Clean. Effective.