Исключение Delphi FireMonkey TListBox AddObject на Android

У меня возникла проблема с добавлением значения TObject в FireMonkey TListBox в Delphi 10.0 Seattle.

Исключение возникает при приведении переменной Integer к указателю TObject.

Я пробовал приведение к TFmxObject безуспешно. В Windows приведение работает как чудо, но на Android это исключение.

Вот мой код:

var
  jValue:TJSONValue;
  i,total,id: integer;
  date: string;
begin
  while (i < total) do
  begin
    date := converteDate(jValue.GetValue('date' + IntToStr(i), ''));
    id := StrToInt(jValue.GetValue('id' + IntToStr(i), ''));
    ListBox1.Items.AddObject(date, TObject(id));
    i := i + 1;
  end;
end;

person Eder    schedule 09.03.2017    source источник


Ответы (1)


Проблема в том, что на iOS и Android (а вскоре и на Linux) TObject использует автоматический подсчет ссылок для управления жизненным циклом, и поэтому вы не можете приводить целочисленные значения как указатели TObject, как вы можете в Windows и OSX, которые не используют ARC. В системах ARC указатели TObject должны указывать на реальные объекты, поскольку компилятор будет выполнять семантику подсчета ссылок на них. Вот почему вы получаете исключение.

Чтобы сделать то, что вы пытаетесь сделать, вам придется обернуть целочисленное значение внутри реального объекта в системах ARC, например:

{$IFDEF AUTOREFCOUNT}
type
  TIntegerWrapper = class
  public
    Value: Integer;
    constructor Create(AValue: Integer);
  end;

constructor TIntegerWrapper.Create(AValue: Integer);
begin
  inherited Create;
  Value := AValue;
end;
{$ENDIF}

...

ListBox1.Items.AddObject(date, {$IFDEF AUTOREFCOUNT}TIntegerWrapper.Create(id){$ELSE}TObject(id){$ENDIF});

...

{$IFDEF AUTOREFCOUNT}
id := TIntegerWrapper(ListBox1.Items.Objects[index]).Value;
{$ELSE}
id := Integer(ListBox1.Items.Objects[index]);
{$ENDIF}

В противном случае сохраните свои целые числа в отдельном списке, а затем при необходимости используйте индексы элементов TListBox в качестве индексов в этом списке, например:

uses
  .., System.Generics.Collections;

private
  IDs: TList<Integer>;

...

var
  ...
  Index: Integer;
begin    
  ...
  Index := IDs.Add(id);
  try
    ListBox1.Items.Add(date);
  except
    IDs.Delete(Index);
    raise;
  end;
  ...
end;

...

Index := ListBox1.Items.IndexOf('some string');
id := IDs[Index];

Его можно переносить на все платформы, не используя IFDEF и не беспокоясь об ARC.

person Remy Lebeau    schedule 09.03.2017
comment
Можете ли вы мне помочь, у меня похожая проблема stackoverflow .com/questions/54927994/ где поместите {$IFDEF AUTOREFCOUNT} - person Pointer; 28.02.2019
comment
@Pointer Чем этот вопрос отличается от этого? Я склонен закрыть этот вопрос как дубликат - person Remy Lebeau; 28.02.2019