具有返回类型的非异步方法中的模态UIAlertController

时间:2015-08-18 18:06:47

标签: c# ios multithreading uiviewcontroller xamarin

我目前有一个必须实现的方法,需要确切的签名。我无法添加async,因为它返回bool而我无法返回Task<bool>类型。该方法显示模态UIAlertController并等待结果。一旦UIAlertController被解雇,它需要返回结果。目前,该方法不起作用,因为PresentViewController是阻止调用。 UIAlertController从未显示,因此应用程序停留在那里。

以下是方法:

public static bool ShowYesNoMessage(string title, string message)
{
    TaskCompletionSource<bool> tcs = new TaskCompletionSource<bool>();

    UIAlertController alertController = UIAlertController.Create(title, message, UIAlertControllerStyle.Alert);

    alertController.AddAction(UIAlertAction.Create("Yes", UIAlertActionStyle.Default, (action) => tcs.TrySetResult(true)));
    alertController.AddAction(UIAlertAction.Create("No", UIAlertActionStyle.Default, (action) => tcs.TrySetResult(false)));

    //Gets the currently visible view controller and present from this one
    UIHelper.CurrentViewController.PresentViewController(alertController, true, null);

    tcs.Task.Wait();
    return tcs.Task.Result;
}

有没有办法保持UI更新,同时在像“ShowYesNoMessage”这样的阻塞调用中等待方法的结果?也许是iOS相关的方法来阻止UI冻结模态UIAlertController?或者可能是另一种呈现模态视图的方法?

1 个答案:

答案 0 :(得分:0)

您可以使用WaitHandle等待用户回复。可能不是最好的解决方法,但应该有效。

public static bool ShowYesNoMessage(string title, string message)
{
    var resetEvent = new AutoResetEvent(false);
    var result = false;

    // Run in another thread so it doesn't block
    Task.Run(action: () =>
    {
        var alertController = UIAlertController.Create(title, message, UIAlertControllerStyle.Alert);

        alertController.AddAction(
            UIAlertAction.Create(
                "Yes", 
                UIAlertActionStyle.Default, 
                (action) => 
                {
                    result = true;
                    resetEvent.Set();
                }));

        alertController.AddAction(
            UIAlertAction.Create(
                "No", 
                UIAlertActionStyle.Default, 
                (action) => 
                {
                    result = false;
                    resetEvent.Set();
                }));

        InvokeOnMainThread(() => UIHelper.CurrentViewController.PresentViewController(alertController, true, null));
    });

    resetEvent.WaitOne();

    return result;
}

注意:代码尚未经过测试

编辑:代码可能仍会阻止,但让我知道它是怎么回事。我不在mac附近,所以无法测试它。