2015-08-18 61 views
2

我目前有一個方法需要實現,它需要確切的簽名。我無法添加async,因爲它返回bool,我無法創建返回類型Task<bool>。該方法顯示一個模態UIAlertController並等待結果。它需要在UIAlertController解散後返回結果。目前,該方法不起作用,因爲PresentViewController是阻止呼叫。 UIAlertController永遠不會顯示,因此,應用程序停留在那裏。使用返回類型的非異步方法的Modal 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?或者,也許另一種方法來呈現模態視圖?

+0

這很可能是僵局。您是否可以使用[AutoResetEvent](https://msdn.microsoft.com/en-us/library/system.threading.autoresetevent(v = vs.110).aspx)並在另一個線程中運行UIAlertController? – Dealdiane

+0

問題是,如果將UIAlertController放在另一個線程中,它將不會出現... –

+0

當呈現它時使用'InvokeOnMainThread'。 – Dealdiane

回答

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附近,所以無法測試它。