Пару месяцев назад Марко Канту порадовал нас информацией о том, что Android не поддерживает модальные формы и поэтому теперь у нас в Delphi XE5 будет два разных метода ShowModal:

    function ShowModal: TModalResult; overload;
    procedure ShowModal(const ResultProc: TProc<TModalResult>); overload;

Обращение к первому методу на Android вызывает исключение, а второй предлагается использовать следующим образом.
Вместо такого кода:

var
  dlg: TForm1;
begin
  dlg := TForm1.Create(nil);
  try
    // select current value, if avaialble in the list
    dlg.ListBox1.ItemIndex := dlg.ListBox1.Items.IndexOf(edit1.Text);
    if dlg.ShowModal = mrOK then
      // if OK was pressed and an item is selected, pick it
      if dlg.ListBox1.ItemIndex >= 0 then
        edit1.Text := dlg.ListBox1.Items [dlg.ListBox1.ItemIndex];
  finally
    dlg.Free;
  end;
end;

нужно писать такой:

var
  dlg: TForm1;
begin
  dlg := TForm1.Create(nil);
  // select current value, if avaialble in the list
  dlg.ListBox1.ItemIndex := dlg.ListBox1.Items.IndexOf(Edit1.Text);
  dlg.ShowModal(
    procedure(ModalResult: TModalResult)
    begin
      if ModalResult = mrOK then
      // if OK was pressed and an item is selected, pick it
        if dlg.ListBox1.ItemIndex >= 0 then
          edit1.Text := dlg.ListBox1.Items [dlg.ListBox1.ItemIndex];
      dlg.DisposeOf;
    end);
end;

Идея ясна и мотивация вполне понятна. Код, который должен выполниться после закрытия формы, перемещается в анонимную процедуру, которая и будет вызвана в нужный момент.

Этот код будет работать на всех платформах. Спасибо, Марко!

Но есть нюанс. Давайте заглянем внутрь новой версии ShowModal:

procedure TCommonCustomForm.ShowModal(const ResultProc: TProc<TModalResult>);
begin
  FResultProc := ResultProc;
  Show;
end;

Такая форма будет одинаково немодальна на всех платформах! То есть, если мы хотим писать кроссплатформенных код, нам предлагают либо усыпать код IFDEF-ами, либо отказаться от использования модальных форм совсем. Как-то это нехорошо.

Не знаю как у вас, но у меня в коде часто встречается что-то такое:

with TForm1.Create(nil) do
try
  ShowModal;
finally
  Free;
end;

С учетом андроида этот код можно переписать следующим образом:

var
  Frm: TForm1;
begin
  Frm := TForm1.Create(nil);
  ShowModal(procedure (Res: TModalResult) begin Frm.DisposeOf; end);
end;

Этот вариант корректно работает на всех платформах, но форма перестает быть модальной и это приемлемо далеко не всегда. Поэтому оптимальный для меня вариант будет выглядеть так:

var
  Frm: TForm1;
begin
  Frm := TForm1.Create(nil);
  {$IFDEF ANDROID}
    Frm.ShowModal(procedure (Res: TModalResult) begin end);
  {$ELSE}
    try
      Frm.ShowModal;
    finally
      Frm.Free;
    end;
  {$ENDIF}
end;

Этот код обеспечит модальность формы в обычных случаях и «всевдомодальность» на андроиде. Но как-то это не очень красиво. Не люблю применять IFDEF-ы по пустякам. Таких мест в коде может быть много.

Подведу итог. В связи с вышеизложенным у меня есть два риторических вопроса.

1) Почему нельзя было новый ShowModal реализовать хотя бы так:

procedure TCommonCustomForm.ShowModal(const ResultProc: TProc<TModalResult>);
begin
  {$IFDEF ANDROID}
    FResultProc := ResultProc;
    Show;
  {$ELSE}
    ResultProc(ShowModal);
  {$ENDIF}
end;

?

2) Если такой подход все-таки чем-то не устраивает, то зачем было называть новый метод ShowModal, ведь он с модальными формами никак не связан?