Delphi FireMonkey TListBox Исключение AddObject для Android
У меня проблема с добавлением TObject
значение для FireMonkey TListBox
в Delphi 10.0 Сиэтл
Исключение повышается при сотворении 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;
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.