在 Delphi Android FMX 中使用 TStringList.AddObject
Using TStringList.AddObject in Delphi Android FMX
我正在为 Android 编译的 Delphi 10.3.3 应用程序中有一个 FMX TCombobox。我之前研究过这个主题并发现 Using Primitive Types with TStrings in iOS。我下载了BoxPrimitives.pas
和下面的代码,在Delphi10.3.3.
下编译成功
uses BoxPrimitives;
{$ifdef ANDROID}
cbGender.Items.AddObject('Male', TBoxInteger(1));
cbGender.Items.AddObject('Female', TBoxInteger(0));
{$else}
cbGender.Items.AddObject('Male', TObject(1));
cbGender.Items.AddObject('Female', TObject(0));
{$endif}
现在我在 Delphi 10.4.1 中打开了源代码,BoxPrimitives.Pas
不再编译。
[DCC Error] BoxPrimitives.pas(46): E2123 PROCEDURE, FUNCTION,
PROPERTY, or VAR expected
一般的问题是:Delphi 10.4 中有什么改变阻止了它的编译?更具体地说:有没有办法在 Delphi 10.4 中使用 AddObject
和 TCombobox
in Android
?
根据 Dalija 的评论,答案是修改代码,使其看起来像这样:
{$if defined(Android) and (CompilerVersion < 34)}
uses BoxPrimitives
{$endif}
{$if defined(Android) and (CompilerVersion < 34)}
cbGender.Items.AddObject('Male', TBoxInteger(1));
cbGender.Items.AddObject('Female', TBoxInteger(0));
{$else}
cbGender.Items.AddObject('Male', TObject(1));
cbGender.Items.AddObject('Female', TObject(0));
{$endif}
在 RAD Studio 10.4 中,Embarcadero 决定在其移动平台上删除 ARC for object lifetime management。
What's New in RAD Studio 10.4 Sydney
Unified Memory Management
Delphi memory management is now unified across all supported platforms - mobile, desktop, and server - using the classic implementation of object memory management. Compared to Automatic Reference Counting (ARC), this offers better compatibility with existing code and simpler coding for components, libraries, and end-user applications. The ARC model remains for string management and interface type references for all platforms.
For C++, this change means that the creation and deletion of Delphi-style classes in C++ follow normal memory management just like any heap-allocated C++ class, significantly reducing complexity.
在所有 Delphi 编译器版本和平台上检测何时使用 ARC 对象生命周期管理的 正确 方法是使用 {$IFDEF AUTOREFCOUNT}
。 BoxPrimitives.pas
单元中甚至提到了这一点:
this class is only for use by AUTOREFCOUNT compilers
例如:
{$ifdef AUTOREFCOUNT}
uses BoxPrimitives;
{$endif}
{$ifdef AUTOREFCOUNT}
cbGender.Items.AddObject('Male', TBoxInteger(1));
cbGender.Items.AddObject('Female', TBoxInteger(0));
{$else}
cbGender.Items.AddObject('Male', TObject(1));
cbGender.Items.AddObject('Female', TObject(0));
{$endif}
...
var Value: Integer;
{$ifdef AUTOREFCOUNT}
Value := TBoxInteger(cbGender.Items.Objects[index]);
{$else}
Value := Integer(cbGender.Items.Objects[index]);
{$endif}
也就是说,我可能会更进一步,通过编辑 BoxPrimitives.pas
以用 {$IFDEF AUTOREFCOUNT} ... {$ELSE} ... {$ENDIF}
包围它的代码,然后在 {ELSE}
部分定义 TBoxInteger
(和其他类型)作为简单的别名,例如:
interface
{$ifdef AUTOREFCOUNT}
uses
Classes, Types, Generics.Defaults;
type
TRSBoxPrimitive<T> = class(TObject)
...
end;
TBoxInteger = TRSBoxPrimitive<Integer>;
TUnboxInteger = TBoxInteger;
...
{$else}
type
TBoxInteger = TObject;
TUnboxInteger = Integer;
...
{$endif}
implementation
{$ifdef AUTOREFCOUNT}
...
{$endif}
end.
那么你根本不需要 {$IFDEF}
你的 AddObject()
调用,只需在所有平台上无条件地使用 TBoxInteger
和 TUnboxInteger
,例如:
// look ma, no IFDEF's!
uses BoxPrimitives;
cbGender.Items.AddObject('Male', TBoxInteger(1));
cbGender.Items.AddObject('Female', TBoxInteger(0));
...
var Value: Integer;
Value := TUnboxInteger(cbGender.Items.Objects[index]);
我正在为 Android 编译的 Delphi 10.3.3 应用程序中有一个 FMX TCombobox。我之前研究过这个主题并发现 Using Primitive Types with TStrings in iOS。我下载了BoxPrimitives.pas
和下面的代码,在Delphi10.3.3.
uses BoxPrimitives;
{$ifdef ANDROID}
cbGender.Items.AddObject('Male', TBoxInteger(1));
cbGender.Items.AddObject('Female', TBoxInteger(0));
{$else}
cbGender.Items.AddObject('Male', TObject(1));
cbGender.Items.AddObject('Female', TObject(0));
{$endif}
现在我在 Delphi 10.4.1 中打开了源代码,BoxPrimitives.Pas
不再编译。
[DCC Error] BoxPrimitives.pas(46): E2123 PROCEDURE, FUNCTION, PROPERTY, or VAR expected
一般的问题是:Delphi 10.4 中有什么改变阻止了它的编译?更具体地说:有没有办法在 Delphi 10.4 中使用 AddObject
和 TCombobox
in Android
?
根据 Dalija 的评论,答案是修改代码,使其看起来像这样:
{$if defined(Android) and (CompilerVersion < 34)}
uses BoxPrimitives
{$endif}
{$if defined(Android) and (CompilerVersion < 34)}
cbGender.Items.AddObject('Male', TBoxInteger(1));
cbGender.Items.AddObject('Female', TBoxInteger(0));
{$else}
cbGender.Items.AddObject('Male', TObject(1));
cbGender.Items.AddObject('Female', TObject(0));
{$endif}
在 RAD Studio 10.4 中,Embarcadero 决定在其移动平台上删除 ARC for object lifetime management。
What's New in RAD Studio 10.4 Sydney
Unified Memory Management
Delphi memory management is now unified across all supported platforms - mobile, desktop, and server - using the classic implementation of object memory management. Compared to Automatic Reference Counting (ARC), this offers better compatibility with existing code and simpler coding for components, libraries, and end-user applications. The ARC model remains for string management and interface type references for all platforms.
For C++, this change means that the creation and deletion of Delphi-style classes in C++ follow normal memory management just like any heap-allocated C++ class, significantly reducing complexity.
在所有 Delphi 编译器版本和平台上检测何时使用 ARC 对象生命周期管理的 正确 方法是使用 {$IFDEF AUTOREFCOUNT}
。 BoxPrimitives.pas
单元中甚至提到了这一点:
this class is only for use by AUTOREFCOUNT compilers
例如:
{$ifdef AUTOREFCOUNT}
uses BoxPrimitives;
{$endif}
{$ifdef AUTOREFCOUNT}
cbGender.Items.AddObject('Male', TBoxInteger(1));
cbGender.Items.AddObject('Female', TBoxInteger(0));
{$else}
cbGender.Items.AddObject('Male', TObject(1));
cbGender.Items.AddObject('Female', TObject(0));
{$endif}
...
var Value: Integer;
{$ifdef AUTOREFCOUNT}
Value := TBoxInteger(cbGender.Items.Objects[index]);
{$else}
Value := Integer(cbGender.Items.Objects[index]);
{$endif}
也就是说,我可能会更进一步,通过编辑 BoxPrimitives.pas
以用 {$IFDEF AUTOREFCOUNT} ... {$ELSE} ... {$ENDIF}
包围它的代码,然后在 {ELSE}
部分定义 TBoxInteger
(和其他类型)作为简单的别名,例如:
interface
{$ifdef AUTOREFCOUNT}
uses
Classes, Types, Generics.Defaults;
type
TRSBoxPrimitive<T> = class(TObject)
...
end;
TBoxInteger = TRSBoxPrimitive<Integer>;
TUnboxInteger = TBoxInteger;
...
{$else}
type
TBoxInteger = TObject;
TUnboxInteger = Integer;
...
{$endif}
implementation
{$ifdef AUTOREFCOUNT}
...
{$endif}
end.
那么你根本不需要 {$IFDEF}
你的 AddObject()
调用,只需在所有平台上无条件地使用 TBoxInteger
和 TUnboxInteger
,例如:
// look ma, no IFDEF's!
uses BoxPrimitives;
cbGender.Items.AddObject('Male', TBoxInteger(1));
cbGender.Items.AddObject('Female', TBoxInteger(0));
...
var Value: Integer;
Value := TUnboxInteger(cbGender.Items.Objects[index]);