Delphi从Android上的Form删除FireMonkey元素 [英] Delphi delete FireMonkey element from Form on Android
问题描述
我在 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屋!