What I'm trying to achieve, in simplified form, is to create a list of dynamically created buttons. When clicking on one of the buttons it should be removed from the list and its object should be freed. My approach is :
- Create a
TList<TButton>
- Create a couple of
TButton
objects and add them to theTList<TButton>
- Assign the
Form
as theParent
for each of the createdTButton
objects - Assign a
Position
for each of the createdTButton
objects - Assign an
OnClick
handler method to each of the createdTButton
objects - The
OnClick
handler sets theSender
TButton
'sParent
tonil
and deletes it from theTList<TButton>
, so that ARC can free theTButton
object that was clicked on.
When I click on one of the dynamically created buttons, I get a "Segmentation Fault". I suspect it is because I am freeing the TButton
object in its own OnClick
handler and the class is trying to do some other stuff with it after my handler.
I have tested this on Android. I assume the same will happen on iOS, or any other ARC platform for that matter.
Is there a better/right way to do this, or another approach I should be following to get it working the way I want?
Here is some example code. It is for a form with one design-time button (Button1
) on it. Clicking this button repeatedly dynamically creates new buttons and adds them to the list.
unit Unit2;
interface
uses
System.SysUtils, System.Types, System.UITypes, System.Classes, System.Variants,
FMX.Types, FMX.Controls, FMX.Forms, FMX.Graphics, FMX.Dialogs,
FMX.Controls.Presentation, FMX.StdCtrls, System.Generics.Collections;
type
TForm2 = class(TForm)
Button1: TButton;
procedure Button1Click(Sender: TObject);
procedure FormCreate(Sender: TObject);
private
ButtonList : TList<TButton>;
procedure ButtonClick(Sender: TObject);
{ Private declarations }
public
{ Public declarations }
end;
var
Form2: TForm2;
implementation
{$R *.fmx}
procedure TForm2.ButtonClick(Sender: TObject);
var
pos : Integer;
begin
pos := ButtonList.IndexOf(TButton(Sender));
TButton(Sender).Parent := nil;
ButtonList.Delete(pos);
end;
procedure TForm2.FormCreate(Sender: TObject);
begin
ButtonList := TList<TButton>.Create;
end;
procedure TForm2.Button1Click(Sender: TObject);
var
pos : Integer;
begin
pos := ButtonList.Add(TButton.Create(nil));
ButtonList.Items[pos].Parent := Form2;
ButtonList.Items[pos].Position.Y := 50 * ButtonList.Count;
ButtonList.Items[pos].OnClick := ButtonClick;
end;
end.