Last active
April 10, 2023 12:42
-
-
Save seanfisher/66bdf388351c1c2a18931deac986bbff to your computer and use it in GitHub Desktop.
A pattern for a Xamarin.iOS controller that permits "safe" async lifecycle methods.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Threading.Tasks; | |
using UIKit; | |
namespace Seanfisher.Gists | |
{ | |
public abstract class AsyncInitializationController : UIViewController | |
{ | |
Task _viewDidLoadAsyncTask = Task.CompletedTask; | |
public virtual Task ViewDidLoadAsync() | |
{ | |
return _viewDidLoadAsyncTask; | |
} | |
public sealed override async void ViewDidLoad() | |
{ | |
try | |
{ | |
base.ViewDidLoad(); | |
_viewDidLoadAsyncTask = ViewDidLoadAsync(); | |
await _viewDidLoadAsyncTask; | |
} | |
catch (Exception e) | |
{ | |
// Handle | |
} | |
} | |
Task _viewWillAppearAsyncTask = Task.CompletedTask; | |
public virtual Task ViewWillAppearAsync() | |
{ | |
return _viewWillAppearAsyncTask; | |
} | |
public sealed override async void ViewWillAppear(bool animated) | |
{ | |
try | |
{ | |
await _viewDidLoadAsyncTask; | |
base.ViewWillAppear(animated); | |
_viewWillAppearAsyncTask = ViewWillAppearAsync(); | |
await _viewWillAppearAsyncTask; | |
} | |
catch (Exception e) | |
{ | |
// Handle | |
} | |
} | |
Task _viewDidAppearAsyncTask = Task.CompletedTask; | |
public virtual Task ViewDidAppearAsync() | |
{ | |
return _viewDidAppearAsyncTask; | |
} | |
public sealed override async void ViewDidAppear(bool animated) | |
{ | |
try | |
{ | |
await _viewDidLoadAsyncTask; | |
await _viewWillAppearAsyncTask; | |
base.ViewDidAppear(animated); | |
_viewDidAppearAsyncTask = ViewDidAppearAsync(); | |
await _viewDidAppearAsyncTask; | |
} | |
catch (Exception e) | |
{ | |
// Handle | |
} | |
} | |
} | |
// Example Usage | |
public class MyController : AsyncInitializationController | |
{ | |
// Override ViewDidLoadAsync instead of ViewDidLoad | |
public override async Task ViewDidLoadAsync() | |
{ | |
await SomeInitializationLogicAsync(); | |
} | |
public override async Task ViewWillAppearAsync() | |
{ | |
// Here it's guaranteed that the ViewDidLoadAsync finished completely | |
// before calling this line, which is NOT guaranteed | |
// with the normal UIViewController lifecycle methods if they run | |
// async tasks. | |
await SomeViewPreparationLogicAsync(); | |
} | |
} | |
} |
@BatriderLEL I added a simple sample controller class. Does that help?
How can I access the Page (and its ViewModel) associated to the async controller? What to do into the page OnAppearing() method? Is it useless now?
Thanks.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Any sample how to use it :|? Thanks!