Поведение ShowMessage () в FireMonkey на iOS - PullRequest
0 голосов
/ 28 апреля 2018

У меня есть простое приложение C ++ для нескольких устройств FMX Приложение имеет 1 форму и больше ничего. В событии OnShow формы я запускаю функцию с именем StartupCode(). Весь код показан ниже.

Когда я запускаю приложение на Windows , я получаю ожидаемое поведение - 3 сообщения всплывают в правильном порядке с правильной синхронизацией (например, каждое Sleep() запускается только после того, как предыдущее диалоговое окно было подтверждается нажатием OK).

Когда я запускаю приложение на iOS или Android , я получаю последнее всплывающее сообщение первым («Спал 2 секунды»), но только по истечении всего времени (12,25 секунды). ). Затем, сразу же после подтверждения, нажав кнопку «ОК», я получаю сообщение «Спал 10 секунд», и после этого я получаю сообщение «Спал четверть секунды».

#include <System.SysUtils.hpp>

void StartupCode()
{
    Sleep(250);
    ShowMessage("Slept quarter sec");
    Sleep(10000); 
    ShowMessage("Slept 10 sec");
    Sleep(2000); 
    ShowMessage("Slept 2 sec");
}

void __fastcall TForm1::FormShow(TObject *Sender)
{
    #if defined(_PLAT_IOS) || defined(_PLAT_ANDROID)
      TThread::ForceQueue(nullptr, [this](){StartupCode();});
    #endif

    #if defined(_PLAT_MSWINDOWS)
      StartupCode();
    #endif
}

Я зеленый и просто пытаюсь немного научиться. Я тестировал, чтобы выяснить, не возникнет ли у потока проблемы с таймерами запуска приложений Apple, когда я столкнулся с таким странным поведением.

Почему это происходит?

1 Ответ

0 голосов
/ 28 апреля 2018

ShowMessage() просто ведет себя по-другому на мобильных платформах в 10.2 Токио, чем вы ожидаете.

Согласно документации 10.2 Токио :

ShowMessage ведет себя по-разному на разных платформах

На настольных платформах ShowMessage ведет себя синхронно. Вызов завершается только тогда, когда пользователь закрывает диалоговое окно.

На мобильных платформах ShowMessage ведет себя асинхронно. Вызов завершается мгновенно, пользователь не ждет закрытия диалогового окна .

Если вы хотите настроить определенное поведение на разных платформах, используйте IFMXDialogServiceAsync.ShowMessageAsync или IFMXDialogServiceSync.ShowMessageSync из FMX.Platform.

Согласно документации 10.0 Сиэтла :

На мобильных платформах звонки на ShowMessage не блокируются. Это означает, что любой код, который вы помещаете после вызова ShowMessage, выполняется до закрытия диалогового окна . Если вам нужно выполнить код после закрытия диалогового окна, используйте MessageDlg вместо ShowMessage.

Итак, в вашем случае происходит то, что ваши звонки на ShowMessage() немедленно возвращаются на StartupCode(), ставя в очередь диалоги в фоновом режиме. Затем все вызовы Sleep() обрабатываются, а затем выполнение возвращается обратно в основной цикл пользовательского интерфейса, который затем отображает все 3 диалоговых окна одновременно, один поверх другого, первый внизу и последний на вершине. Вот почему вы видите их в обратном порядке.


Примечание: Android не поддерживает модальные / синхронные диалоги! И как таковой, IFMXDialogServiceSync.ShowMessageSync() не реализован на Android, реализован только IFMXDialogServiceAsync.ShowMessageAsync().

До 10.1 Берлина ShowMessage() внутренне назывался синхронной версией IFMXDialogService.MessageDialog() (вопреки тому, что сказано в документации Сиэтла выше), которая работала на iOS, но вызвала ENotImplemented исключение на Android.

ShowMessage()MessageDlg()) было устарело в 10,1 Berlin .

У меня не установлено 10.1 Berlin или 10.2 Tokyo, чтобы проверить, что ShowMessage() делает внутри этих систем, но похоже, что оно было обновлено для использования IFMXDialogServiceAsync.ShowMessageAsync() на iOS и Android, если вы не получаете ENotImplemented исключение на Android.


Примечание: поведение, которое вы видите, НИЧЕГО не имеет отношения к TThread::ForceQueue() (что сломано на Android в 10.2 Токио , BTW). Кроме того, TThread::ForceQueue() не запускает новый поток, как вы утверждали.

...