【问题标题】:Access violation when opening form 2th time on Android in Delphi XE7在 Delphi XE7 中的 Android 上第二次打开表单时访问冲突
【发布时间】:2015-04-30 06:42:24
【问题描述】:

当我第一次打开我的表单时,我没有发现违规,但是当我第一次选择 TEdit 字段然后关闭表单,然后重新创建表单并打开它时,我得到了违规。

创建表单的代码:

procedure TfrmNocoreDKS.actConfigExecute(Sender: TObject);
var
  confForm: TConfiguratie;
begin
  confForm := TConfiguratie.Create(nil);
  confForm.ShowModal(
    procedure(ModalResult: TModalResult)
    begin
      confForm.DisposeOf;//Also tried confForm.Free;
    end);
end;

我也试过这个来创建表单:

procedure TfrmNocoreDKS.actConfigExecute(Sender: TObject);
var
  confForm: TConfiguratie;
begin
  confForm := TConfiguratie.Create(nil);
  try
    confForm.ShowModal(
      procedure(ModalResult: TModalResult)
      begin
      end);
  finally
    confForm.free;
  end;
end;

关闭表单的代码:

procedure TConfiguratie.FormClose(Sender: TObject; var Action: TCloseAction);
begin
  Action := TCloseAction.caFree;
end;

因为仅当您单击任何 TEdit 然后关闭表单时才会出现违规行为,我认为它与虚拟键盘有关,但我不确定。我没有任何使用虚拟键盘本身的方法。

【问题讨论】:

  • 尝试完全删除 FormClose。您要发布两次表单。
  • @DalijaPrasnikar 是的,谢谢。好像解决了!奇怪的是,在 embarcadero 网站上,它说你必须使用它。
  • @DalijaPrasnikar,这是不能使用DisposeOf() 的情况。详情请见ShowModal on Android
  • @LURD 我还找到了 Android 上 showModal 的教程,但在这种情况下它不正确。
  • 在不支持模态对话框的移动平台上使用ShowModal 时,您观察到的任何情况都算作the documentation 警告的“意外行为”吗?

标签: android forms delphi firemonkey delphi-xe7


【解决方案1】:

这个问题似乎只在 Delphi XE7 中出现。我现在用的是Delphi XE8,没有这个问题了。

【讨论】:

    【解决方案2】:

    更新

    虽然我在此处的建议已记录在案,但 Android 和多种表单仍然存在问题。请参阅本文后面的内容。


    根本不要打电话给DisposeOf()FreeFormClose()caFree 调用是使其工作的关键。

    如何处理模态对话框的文档已更改:Using FireMonkey Modal Dialog Boxes

    FireMonkey 的架构师已经为此苦苦挣扎了几个版本,终于成功了

    文档中的示例如何创建模式对话框:

    procedure MyCurrentForm.MyButtonClick(Sender: TObject);
    var
      dlg: TMyModalForm;
    begin
      // Create an instance of a form.
      dlg := TMyModalForm.Create(nil);
    
      // Configure the form. For example, give it a display name.
      dlg.Caption := 'My Modal Dialog Box';
    
      // Show your dialog box and provide an anonymous method that handles the closing of your dialog box.
      dlg.ShowModal(
        procedure(ModalResult: TModalResult)
        begin
          // Do something.
        end
      );
    end;
    

    释放你的模态对话框:

    procedure TMyModalForm.FormClose(Sender: TObject; var Action: TCloseAction);
    begin
      Action := TCloseAction.caFree;
    end;
    


    更新

    OP 已尝试过此解决方案,但无法按预期工作。

    在调查 QC 时,有报告称这在移动 android 平台上无法按预期工作:

    RSP-9692 Runtime creation of forms in Android

    RSP-9665 Access Violation in FMX.Platform.Android SendCMGestureMessage.

    (您必须登录才能访问它们)。

    后者解释了正在发生的事情。当模态窗体被销毁时,FFocusedControl 可能指向已销毁的控件。当 ARC 试图释放 FFocusedControl 时,这将导致分段错误。 FFocusedControl 必须声明为 [weak]。有关详细信息,请参阅 RSP-9665。

    还有QC-126524 [Android] Open/Close/Free sub form multiple times may cause crash on Android Platform when removing Focus from TEdit 报告同样的事情并在 XE7 中解决并关闭。这显然不是真的。

    【讨论】:

    • 我也试过这个,但我仍然得到这个错误。所以我猜@DalijaPrasnikar 的方式是正确的。
    • 你确定你删除了 DisposeOf() 调用吗?它根本不应该存在。
    • 是的,我已将其删除。奇怪的是,我在其他表单上没有这个问题。
    • 别忘了将模态对话框OnClose事件设置为FormClose
    • 关于 TEdit 的链接对我来说似乎是个问题。感谢您的链接!似乎它在 XE7 中没有解决。
    【解决方案3】:

    Embarcadero documentation 关于 FMX ShowModal 和移动平台的说法

    注意:Android 应用不支持模态对话框。您应该调用 Show,而不是调用 ShowModal,并让表单返回并调用您的事件。我们建议您不要在任一移动平台(iOS 和 Android)上使用模式对话框,因为可能会导致意外行为。不使用模式对话框可以消除调试和支持移动应用程序的潜在问题。

    【讨论】:

    • ShowModal 在内部调用 Show。所以 buttonclick 方法中没有任何阻塞。 ShowModal 调用之后的任何代码都将在匿名方法之前执行。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多