【问题标题】:Delphi delete FireMonkey element from Form on AndroidDelphi从Android上的Form中删除FireMonkey元素
【发布时间】:2023-03-31 23:03:01
【问题描述】:

我在 OnShow 事件中使用此代码在我的表单上创建了一个元素:

procedure TForm4.FormShow(Sender: TObject);
var
  VertScrollLink:TVertScrollBox;
begin
  VertScrollLink := TVertScrollBox.Create(form4);
  VertScrollLink.Align := TAlignLayout.Client;
  VertScrollLink.Parent := form4;
end;

在某些操作中,我需要动态删除布局:

for LIndex := form4.ComponentCount-1 downto 0 do
begin
  if (form4.Components[LIndex].ToString='TVertScrollBox') then
  begin
    //showmessage(form4.Components[LIndex].ToString);
    form4.Components[LIndex].Free;
  end;
end;

此代码在 Windows 上运行良好,但在 Android 上不会删除任何内容。

【问题讨论】:

  • ARC 正在燃烧你。值得一读。 ToString 是一种测试类型的奇怪方法。这不是 PHP。使用is 运算符。您没有使用 XE。我删除了那个标签。
  • @DavidHeffernan 是的,我也使用 PHP :) 我将if (form4.Components[LIndex].ToString='TVertScrollBox') then 更改为if (form4.Components[LIndex] is TVertScrollBox) then,但没有任何改变!!问题似乎在form4.Components[LIndex].Free; !!!
  • 是的,我知道。 ARC是伤害你的东西。这就是我所说的。为什么你会期望 Free 在 ARC 上做任何事情。你了解 ARC。

标签: delphi firemonkey delphi-xe7 delphi-10-seattle delphi-10.1-berlin


【解决方案1】:

原因是Delphi uses Automatic Reference Counting for Objects 在移动平台(iOS 和 Android)上,而不是在桌面平台(Windows 和 OSX)上。你的Free() 实际上是一个空操作,因为从Components[] 属性访问组件会增加它的引用计数,然后Free() 会减少它(事实上,编译器应该已经发出关于代码的警告没有影响)。该组件仍然有对它的活动引用(它的OwnerParent),所以它实际上并没有被释放。

如果要强制释放组件,需要调用DisposeOf(),例如:

for LIndex := form4.ComponentCount-1 downto 0 do
begin
  if form4.Components[LIndex] is TVertScrollBox then
  begin
    form4.Components[LIndex].DisposeOf;
  end;
end;

或者,删除活动引用并让 ARC 正常处理销毁:

var
  VertScrollLink: TVertScrollBox;
  LIndex: Integer;
begin
  ...
  for LIndex := form4.ComponentCount-1 downto 0 do
  begin
    if form4.Components[LIndex] is TVertScrollBox then
    begin
      VertScrollLink := TVertScrollBox(form4.Components[LIndex]);
      VertScrollLink.Parent := nil;
      VertScrollLink.Owner.RemoveComponent(VertScrollLink);
      VertScrollLink := nil;
    end;
  end;
  ...
end;

话虽如此,您可能会考虑跟踪您创建的组件,以便以后无需使用循环来查找它:

type
  TForm4 = class(TForm)
    procedure FormShow(Sender: TObject);
    ...
  private
    VertScrollLink: TVertScrollBox;
    ...
  end;

procedure TForm4.FormShow(Sender: TObject);
begin
  VertScrollLink := TVertScrollBox.Create(Self);
  VertScrollLink.Align := TAlignLayout.Client;
  VertScrollLink.Parent := Self;
end;

begin
  ...
  if Assigned(VertScrollLink) then
  begin
    VertScrollLink.DisposeOf;
    { or:
    VertScrollLink.Parent := nil;
    VertScrollLink.Owner.RemoveComponent(VertScrollLink);
    }
    VertScrollLink := nil;
  end;
  ...
end;

【讨论】:

  • 为什么 ARC 没有记录在 delphi 本地帮助中!?
  • @roozgar:实际上是这样。至少在最近的版本中。例如,在西雅图 10.0 中,这是 ARC 的本地帮助主题:mk:@MSITStore:C:\Program%20Files\Embarcadero\Studio\17.0\help\Doc\topics.chm::/Automatic_Reference_Counting_in_Delphi_Mobile_Compilers.htm
猜你喜欢
  • 2015-04-24
  • 1970-01-01
  • 1970-01-01
  • 2017-07-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多