Unexpected side-effect of TileList UnloadTile

I've encountered strange behavior of unexpected control de-allocation after TileList OnUnload is called.
I really do not know, if it's FMX-specific, or TMS is to blame. In a nutshell, I have TileList, which uses non-standard tile contents (all TileOptions are unchecked). Layout with custom content is created owned by the form object, in OnTileLoad handler, custom content is assigned as child to the TileShape. In OnTileUnload, custom content is being unparented from TileShape, as appropriate.
Nevertheless, when Tiles got shuffled using mouse hold-and-drag, OnUnloadTile is called, custom content is unparented, but then, deleted with tile shape anyways, as if it is still in its child list.
I have created test C++ builder project to reproduce this behavior, archive attached.
If you run test application, and try to reposition tiles with mouse, you will see, that custom content with text will disappear, as soon as corresponding tile gets unloaded-loaded, somehow removing text, which is obviously unparented at the moment.
Optional text log is maintained to show an order of tile unload; text content removal operations.


At the time of unload, the unloaded tile index is still the original one. Searching for the content with the datastring property in a tile that hasn't been given a new index will remove the one from the drag tile, instead of the one from the new tile. The Load procedure will load the tiles with the correct index. Instead of re-using objects that are created, you will need to create the object in the Load and destroy it in the unload. The unique identifier is the datastring property which is initialized in the constructor.

#define LOG(t)</div>
if( !Application->Terminated ) { </div>
  Form1->log_->Lines->Add( t ); </div>
  Form1->log_->GoToTextEnd(); }


class TestText : public TTMSFMXHTMLText
  __fastcall TestText(TComponent* owner, const UnicodeString& name) :
Text = name;
HitTest = false;
Align = TAlignLayout::Client;

  virtual __fastcall ~TestText()
LOG( UnicodeString::Format("TestText '%s' destroyed", ARRAYOFCONST((Text.c_str())) ) )

fastcall TForm1::TForm1(TComponent* Owner)
  : TForm(Owner)
  for(int idx = 0; idx < 9; ++idx)
TTMSFMXTile* tile = tl->Tiles->Add();
tile->DataString = "tile" + UnicodeString(tile->Index);

void __fastcall TForm1::tl_UnLoadTile(TObject *Sender, TTMSFMXTile ATile, TControl ATileShape)
  TestText txt = dynamic_cast<TestText>(ATile->DataObject);
  if (txt) {
txt = 0;

void __fastcall TForm1::tl_LoadTile(TObject *Sender, TTMSFMXTile *ATile, TControl ATileShape)
  TestText txt = new TestText(this, ATile->DataString);
  ATile->DataObject = txt;
void _fastcall TForm1::Button1Click(TObject *Sender)

I intentionally try to stick to content re-use, instead of re-creation at each tile re-load.

In real life application there is quite complicated view, with persistent states, etc.
Is there any way to keep custom content reusable? 

The design of the tilelist currently doesn't allow this. We will need to investigate if we can improve this behavior.

Hmm... I thoroughly studied FMX.TMSTileList.pas code, as far as my rusty Pascal knowledge allowed it, and found nothing, that may stop content from being re-used, as long as no FMX delayed processing is broken... Will run some futher reserach, and we'll see...

I've noticed, that in TileList code, in all (two) cases, OnUnloadTile call, is followed by tile shape cleanup, with Free|DisposeOf calls.

In my OnUnloadTile handler, I detach custom content from the tile shape, by setting its Parent to 0. So, if everything is correct, at the moment TilShape's Free|DisposeOf is called, custom content is already not child of TileShape, and, as soon as it's owned by the form itself, it should not be deleted, when TileShape is deallocated.
What I see though, is that custom content is being destroyed anyway. And that's I do not understand. No clues, unless some delayed processing is queued when Parent is changed...
Anyways, I've changed TilShape Free|DisposeOf calls to the Release one, which causes object to be marked as being in Deleted state, placed into internal FMX purgatory queue for postponed deletion.
In that case, everything is working as I expected from the start, custom content got successfully detached from tile shapes, being deleted, and subsequent implicit tile shape removal is not causing custom content deallocation any more.


We have introduced a public DelayedUnload property that can be used to switch between a free and release instruction. The next version will have this property included. As a sample, applying this in the constructor of the form should be written as

  tl_->DelayedUnload = True;

Kind Regards, 

That's wjat I like your component suite for, in the first place, flexible and powerful. Great design decision!

Source code needs some refactoring though, in my opinion.:)