在Firemonkey中运行时创建然后销毁TLabel

时间:2015-01-18 19:02:10

标签: delphi firemonkey destroy tlabel

我正在尝试使用此代码在运行时将TLabel生成到VertScrollBox中;

var
   i, f: integer;
   RT_Label: TLabel;
begin
   f:= 10;
   for i := 0 to 20 do
   begin
        RT_Label := TLabel.Create(Self);
        RT_Label.Name := 'Label' + i.ToString;
        RT_Label.Text := 'SampleLabel' + i.ToString;
        RT_Label.Position.Y := f;
        RT_Label.Align := TAlignLayout.Top;
        RT_Label.Parent := VertScrollBox1;
        inc(f, 15);
   end;
end; 

标签显示没有任何问题,但当我尝试使用此代码释放生成的标签时;

var
   i: integer;
   LComponent: TComponent;
begin
   for i := 0 to ComponentCount-1 do
   begin
        if( Components[i] is TLabel )then
         if StartsText('Label', (Components[i] as TLabel).Name) then
         begin
             LComponent := (Components[i] as TLabel);     
             If Assigned(LComponent) then FreeAndNil(LComponent);
         end;
    end;
end;

然后我总是得到错误'Argument out of range'。 有人可以帮我吗?非常感谢和问候。

1 个答案:

答案 0 :(得分:2)

使用以下行开始循环

for i := 0 to ComponentCount-1 do

但是当你释放一个组件时,它会将自己从组件列表中删除,作为清理代码的一部分。因此,每个被释放的组件都会将列表的大小减少1.当for循环开始时,ComponentCount-1表达式将被计算一次,因此不会更新以反映更改。

即使您可以解决此问题,您的循环也会跳过项目。即如果您删除的项目3,项目4现在将成为项目3,但您的循环将进入项目4。

但是,解决这个问题的方法很简单。只需向后迭代列表:

表示i:= ComponentCount-1 downto 0

值得一提的是,您的代码实际上只会释放Windows和OSX上的项目。在移动设备上,编译器使用ARC,只有在删除所有引用后才释放对象。解决方案/解决方法/ fudge [1]是为组件调用DisposeOf而不是Free。

另外,as运算符已经保证对象是Assigned,因此不需要额外的测试。 FreeAndNil不需要一个局部变量,它将被重新分配或直接超出范围,并且在释放之前不需要转换对象。由于Free(或DisposeOf)方法存在于共同的祖先类中,因此编译器将解析任何后代类的链接。

因此,您的代码可以简化为

var
   i: integer;
begin
   for i := ComponentCount-1 downto 0 do
   begin
        if( Components[i] is TLabel )then
         if StartsText('Label', (Components[i] as TLabel).Name) then
           Components[i].DisposeOf;
   end;
end;

[1] - 取决于你与谁交谈。