Collecting user input with async/await?

JoshEarlJoshEarl USMember

I'm working on an app that has to allow the user to scan a barcode, then enter some data about the item that was scanned. Once the data has been collected, the app automatically drops back into scanning mode.

I've implemented this using two callbacks. There's a callback that fires when a scan completes, which shows a UIViewController with the data entry fields. The data collection screen fires another callback when the user hits a Done button.

This seems like the perfect scenario for async and await, but I can't find any examples that match what I'm trying to do.

I did stumble across PresentViewControllerAsync, but I can't find any documentation about how it's supposed to work, and I wasn't able to suss it out with a Hello World app.

To summarize, I'm looking for a way to:

  1. Present a UIViewController.
  2. Use await to halt execution until the user enters data.
  3. Continue execution when the user dismisses the view controller.

Can someone point me in the right direction?

Posts

  • JoshEarlJoshEarl USMember
    edited October 2013

    Found a solution based on this post.

    The .sln in that thread showed how to use async with a UIAlertView, and after some hacking I got it to work with a UIViewController.

    Here's the relevant code:

    using System;
    using System.Threading.Tasks;
    using MonoTouch.Foundation;
    using MonoTouch.UIKit;
    
    namespace AlertAsyncSample
    {
        public partial class AlertAsyncSampleViewController : UIViewController
        {
            public AlertAsyncSampleViewController() : base("AlertAsyncSampleViewController", null) { }
    
            async partial void ShowAlertButtonTapped(NSObject sender) {
    
                var message = await ShowModal();
                ResultLabel.Text = message.ToString();
    
                // this also works
                // Task.Factory.StartNew(async () => {
                //     var message = await ShowModal();
                //     ResultLabel.Text = message;
                // });
            }
    
            public Task<object> ShowModal() 
            {
                var tcs = new TaskCompletionSource<object>();
    
                UIApplication.SharedApplication.InvokeOnMainThread(new NSAction(() =>
                {
                    var modal = new AsyncModalViewController();
                    modal.Dismissed = tcs.SetResult;
                    PresentViewController(modal, true, null);
                }));
    
                return tcs.Task;
            }
        }
    }
    

    I posted the full source on GitHub. (It's messy because I just reused the alert-based project, so there are lots of references to alert.)

  • DualDubDualDub GBMember ✭✭

    Very nice - thanks

Sign In or Register to comment.