iOS 上 FireMonkey 中的 ShowMessage() 行为

ShowMessage() behavoir in FireMonkey on iOS

我有一个简单的 FMX 多设备 C++ 应用程序。该应用程序只有 1 个表格,没有别的。在表单的 OnShow 事件中,我启动了一个名为 StartupCode() 的函数。所有代码如下所示。

当我 运行 Windows 上的应用程序时,我得到了预期的行为 - 3 条消息以正确的顺序和正确的时间弹出(例如,每个 Sleep() 仅在单击“确定”确认前一个对话框后才开始。

当我 运行 iOSAndroid 上的应用程序时,我得到最后一条消息首先弹出("Slept 2 sec"),但仅在整个时间过去后(12.25 秒)。然后在单击“确定”确认后立即收到 "Slept 10 sec" 消息,同样之后我收到 "Slept quarter sec" 消息。

#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 的应用程序启动看门狗计时器而陷入困境。

为什么会发生这种行为?

ShowMessage() 在 10.2 Tokyo 的移动平台上的表现与您预期的完全不同。

根据 10.2 Tokyo documentation:

ShowMessage Behaves Differently On Different Platforms

On desktop platforms, ShowMessage behaves synchronously. The call finishes only when the user closes the dialog box.

On mobile platforms ShowMessage behaves asynchronously. The call finishes instantaneously, it does not wait for the user to close the dialog box.

If you want to force a specific behavior across different platforms, use IFMXDialogServiceAsync.ShowMessageAsync or IFMXDialogServiceSync.ShowMessageSync from the FMX.Platform unit.

根据 10.0 Seattle documentation:

On mobile platforms, calls to ShowMessage are not blocking. This means that any code that you place after a call to ShowMessage is executed before the dialog box closes. If you need to execute code after your dialog box closes, use MessageDlg instead of ShowMessage.

所以,您的情况是您对 ShowMessage() 的调用立即返回到 StartupCode(),在后台排队对话框。然后处理所有对 Sleep() 的调用,然后执行 returns 回到主 UI 循环,然后同时显示所有 3 个对话框,一个在另一个之上, 第一个在底部,最后一个在顶部。这就是为什么您会看到它们以相反的顺序出现。


注意:Android不支持modal/synchronous对话框!因此,IFMXDialogServiceSync.ShowMessageSync() 未在 Android 上实现,仅实现 IFMXDialogServiceAsync.ShowMessageAsync()

在 10.1 Berlin 之前,ShowMessage() 在内部调用了 IFMXDialogService.MessageDialog()synchronous 版本(与上面的西雅图文档所说的相反),它在iOS 但在 Android.

上引发了 ENotImplemented 异常

ShowMessage()(和 MessageDlg())是 deprecated in 10.1 Berlin

我没有安装 10.1 Berlin 或 10.2 Tokyo 来检查 ShowMessage() 在这些系统上的内部功能,但听起来它已更新为在两个 [=70= 上使用 IFMXDialogServiceAsync.ShowMessageAsync() ] 和 Android,如果您在 Android.

上没有收到 ENotImplemented 异常

注意:您看到的行为与 TThread::ForceQueue()(即 broken on Android in 10.2 Tokyo,顺便说一句)无关。此外,TThread::ForceQueue() 不会像您声称的那样启动新线程。