我正在使用RAD Studio XE-5创建Android应用程序,但最近遇到了一个令人费解的错误。TStringList.AddObject 引发以下异常:
Project Project3.apk raised exception class Segmentation fault (11).
我的代码是这样的
procedure TMainForm.FormCreate(Sender: TObject);
var
list: TStrings;
begin
list := TStringList.Create;
list.AddObject('Joe', TObject(1)); // This is where exception is raised
list.AddObject('Hans', TObject(2));
end;
这段代码在 32 位 Windows 目标上运行良好,但在我的 Nexus 7 上运行(在调试模式下)时会引发上述异常(当我不使用 TStringList.AddObject 时运行良好)。如果我在没有调试的情况下运行该应用程序,它只会关闭我的 Nexus。
这是德尔福Android的已知问题/限制吗?是否有解决方法或推荐的方法来达到相同的结果(不仅适用于此玩具示例,也适用于一般使用 AddObject)?
整个编程风格是Delphi 7时代的做事方式。但自那时以来,许多事情都发生了变化。最具体地说,移动编译器使用 ARC,它们将尝试销毁字符串列表中保存的对象。这解释了您看到的错误。
另一个更改是对 D2009 中添加的泛型的支持。现在,您应该为此任务使用类型安全的泛型容器,而不是字符串列表。周围有很多,但让我们展示一个来自 Generics.Collections
的内置类的示例。
您需要创建列表元素类型。它包含一个字符串和一个整数。
type
TMyItem = record
public
Name: string;
Age: Integer;
end;
让我们制作一种简单的方法来制作新的:
function NewMyItem(const Name: string; const Age: Integer): TMyItem;
begin
Result.Name := Name;
Result.Age := Age;
end;
然后让我们列出它们:
var
List: TList<TMyItem>;
....
List := TList<TMyItem>.Create;
现在添加一些项目:
List.Add(NewMyItem('Joe', 1));
List.Add(NewMyItem('Hans', 2));
,为什么Stefan Glienke没有写他们的评论作为答案,但这是一个非常好的另一个答案:
请参阅此博客文章(它谈到了iOS,但同样适用于 安卓): http://blogs.riversoftavg.com/index.php/2013/08/01/using-primitive-types-with-tstrings-in-ios/
建议是创建一个新的包装类来将整数包装到 TObject 中,为它们制作类运算符隐式和显式以方便转换,并使用强制转换为此类而不是将整数转换为 TObject 并返回整数。它最大限度地减少了所需的代码更改。