なんか空いてたのでエントリーしましたが、急だったので軽い話です。
の焼き直しみたいなものです。
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
、覚えておきましょう。