简体   繁体   English

Android上的Delphi FireMonkey TListBox AddObject异常

[英]Delphi FireMonkey TListBox AddObject exception on Android

I'm having a problem adding a TObject value to a FireMonkey TListBox in Delphi 10.0 Seattle. 我在添加一个问题TObject值到FireMonkey TListBox德尔福10.0西雅图。

An exeception is raised when casting an Integer variable to a TObject pointer. Integer变量强制转换为TObject指针时,会引发一种理解。

I tried the cast to TFmxObject with no success. 我尝试将演员表转换为TFmxObject ,但没有成功。 On Windows, the cast works like a charm, but on Android it raises the exception. 在Windows上,强制转换的工作方式像一个超级按钮,但在Android上,它引发了异常。

Here is my code: 这是我的代码:

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;

The problem is that on iOS and Android (and soon Linux), TObject uses Automatic Reference Counting for lifetime management, and as such you cannot type-cast integer values as TObject pointers, like you can on Windows and OSX, which do not use ARC. 问题在于,在iOS和Android(以及不久的Linux)上, TObject使用自动引用计数进行生命周期管理,因此,您不能像在Windows和OSX上那样使用不使用ARC的类型将整数值作为类型的TObject指针进行类型转换。 。 On ARC systems, TObject pointers must point to real objects, as the compiler is going to perform reference-counting semantics on them. 在ARC系统上, TObject指针必须指向实际对象,因为编译器将对它们执行引用计数语义。 That is why you are getting an exception. 这就是为什么您要例外。

To do what you are attempting, you will have to wrap the integer value inside of a real object on ARC systems, eg: 要执行您要尝试的操作,您必须将整数值包装在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}

Otherwise, store your integers in a separate list and then use the indexes of the TListBox items as indexes into that list when needed, eg: 否则,将整数存储在单独的列表中,然后在需要时使用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];

This is portable to all platforms without having to use IFDEF s or worrying about ARC. 它可以移植到所有平台,而不必使用IFDEF或担心ARC。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM