Modal UIAlertController在非异步方法中带返回类型

本文关键字:返回类型 异步方法 UIAlertController Modal | 更新日期: 2023-09-27 18:08:38

我目前有一个方法我必须实现,这需要确切的签名。我不能添加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?或者另一种方法来呈现模态视图?

Modal UIAlertController在非异步方法中带返回类型

您可以使用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附近,所以无法测试。