Delphi从Android上的Form删除FireMonkey元素 [英] Delphi delete FireMonkey element from Form on Android

查看:84
本文介绍了Delphi从Android上的Form删除FireMonkey元素的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I created an element on my Form with this code in the OnShow event:

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

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

On some action, I need to delete the layout dynamically:

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上不会删除任何内容。

This code works good on Windows, but does not delete anything on Android.

推荐答案

原因是因为 Delphi使用了自动引用计数适用于移动平台(iOS和Android)上的对象,而不适用于桌面平台(Windows和OSX)上的对象。您的 Free()实际上是无操作的,因为从 Components [] 属性访问该组件将增加其引用计数,然后 Free()会将其递减(实际上,编译器应该发出有关代码无效的警告)。该组件仍然具有对其的有效引用(其所有者父项),因此实际上并未释放它。

The reason is because Delphi uses Automatic Reference Counting for Objects on mobile platforms (iOS and Android), but not on desktop platforms (Windows and OSX). Your Free() is effectively a no-op, because accessing the component from the Components[] property will increment its reference count, and then the Free() will decrement it (in fact, the compiler should have issued a warning about the code having no effect). The component still has active references to it (its Owner and Parent), so it is not actually freed.

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

If you want to force the component to be freed, you need to call DisposeOf() on it, eg:

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

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

Alternatively, remove the active references and let ARC handle the destruction normally:

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;

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

That being said, you might consider keeping track of the component you create so you don't need to use a loop to find it later:

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;

这篇关于Delphi从Android上的Form删除FireMonkey元素的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆