これは Xamarin Advent Calendar 2014 23日目 の記事です。

 なんか空いてたのでエントリーしましたが、急だったので軽い話です。

の焼き直しみたいなものです。

 iOS8 では、UIAlertDialog が非推奨になり、代わりに UIAlertController を使えとのこと。

 普通に使うとこうなります。

button1.TouchUpInside += (sender, e) => 
{
    var alert = UIAlertController.Create("", "こんぼう をすてますか?", UIAlertControllerStyle.Alert);
    alert.AddAction(UIAlertAction.Create("はい", 
        UIAlertActionStyle.Default, x=> label1.Text = "こんぼう をすてました")); 
    alert.AddAction(UIAlertAction.Create("いいえ",  
        UIAlertActionStyle.Default, x=> {})); 
     
    this.PresentViewController(alert, true, null);
};

 このくらいなら問題ありません。

 次に、こんぼう をすてる前にもう一度問いかけるようにします。
2つ目の UIAlertController が入れ子になってしまって見づらい、 残念な感じ です。

button1.TouchUpInside += (sender, e) => 
{
    var alert = UIAlertController.Create("", "こんぼう をすてますか?", UIAlertControllerStyle.Alert);
    alert.AddAction(UIAlertAction.Create("はい", 
        UIAlertActionStyle.Default, x=> 
        {
            // 念押しの確認ダイアログ(入れ子でつらい
            var alert2 = UIAlertController.Create("", "ほんとうにすてますか?", UIAlertControllerStyle.Alert);
            alert2.AddAction(UIAlertAction.Create("もちろん", UIAlertActionStyle.Default, _=> 
            {
                label1.Text = "こんぼう をすてました"
            }));
        alert2.AddAction(UIAlertAction.Create("やめる",  UIAlertActionStyle.Default, _=> {})); 

        // アラート2の表示
        this.PresentViewController(alert2, true, null);
    })); 

    // アラート1の表示
    alert.AddAction(UIAlertAction.Create("いいえ",  UIAlertActionStyle.Default, x=> {})); 

    this.PresentViewController(alert, true, null);
};

 Objective-C や Swift なら、ここで打つ手は今のところ無いでしょう。
しかし Xamarin には、C# には async/await がありまぁす!
アラートの表示を async/await(というか Task)対応してみましょう。

private Task<int> ShowDialog(string message, string button1Title, string button2Title)
{
    var comp = new TaskCompletionSource<int>();

    var alert = UIAlertController.Create("", message, UIAlertControllerStyle.Alert);
    alert.AddAction(UIAlertAction.Create(button1Title, UIAlertActionStyle.Default, x=> 
    {
        comp.SetResult(1); // OKボタン
    })); 
    alert.AddAction(UIAlertAction.Create(button2Title,  UIAlertActionStyle.Default, x=> 
    {
        comp.SetResult(0); // Cancel
    })); 

    this.PresentViewController(alert, true, null);

    return comp.Task;
}

Task<int> を返すメソッド ShowDialog です。UIAlertController のボタンが押されたら SetResult して Task の値を決定します。

 このメソッドを使う方は、こうなります。

button1.TouchUpInside += async (sender, e) => 
{
    if (await ShowDialog("こんぼう をすてますか?", "はい", "いいえ") == 0) 
        return;

    if (await ShowDialog("ほんとうにすてますか?", "もちろん", "やめる") == 0) 
        return;

    label1.Text = "こんぼう をすてました";
};

なんて見やすいコードになったことでしょう。すばらしい!

入れ子でなく、フラットに書けるので、こんな事もできます。

button1.TouchUpInside += async (sender, e) => 
{
    while (await ShowDialog("こんぼう をすてますか?", "はい", "いいえ") == 1) 
    {
        label1.Text = "それをすてるなんてとんでもない!";
    }

	label1.Text = "すてるのをやめました";
};

こんぼうを捨てるのをあきらめるまで、なんどでも聞いてきます。
コールバックスタイルのメソッドでループとか、ベタに書くと頭痛いです。

動かすとこんな感じです。

ShowDialog は拡張メソッドとして作成しておくと、呼び出しに便利かもしれません。
コールバックスタイルの機能を、Task化するパターンはよく使いそうな気がします。TaskCompletionSource、覚えておきましょう。

Xamarin
iOS
C#

published

Ads

Read more!

amay077

Microsoft MVP(Xamarin). フルリモートワーカー. Geospatial Mobile app developer. Love C#.

amay077 amay077