2013-10-04 29 views
1

我正在使用RAD Studio XE-5创建Android应用程序,但最近偶然发现了一个令人费解的错误。 TStringList.AddObject引发以下异常:TStringList.AddObject不适用于Android(德尔福)

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。

这是Delphi Android的一个已知问题/限制吗?有没有解决方法或推荐的方法来实现相同的结果(不仅仅是这个玩具的例子,但通常使用AddObject)?

+1

Android编译器使用ARC,因此您不能将整数视为像你在Win32/64中做的那样。 –

+0

@StefanGlienke这是否意味着我可以在一个类中包装整数(如Integer在java中),它应该工作? – Daniel

+0

是的,看到这篇博客文章(它谈论iOS,但同样适用于Android):http://blogs.riversoftavg.com/index.php/2013/08/01/using-primitive-types-with-tstrings- in-ios/ –

回答

4

整个编程风格是在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)); 
+1

我可以在列表框中使用这个解决方案吗?我引发这个问题的原始问题是,我试图在列表框中的每个项目上保存一个Id,而ListBox.Items是类型TStrings。 – Daniel

+0

该问题陈述'TStringList',因此我的答案。您不能在列表框中使用此解决方案。 –

+0

FMX中的ListBox是否支持像VCL中的虚拟模式?如果是这样,那么你可以使用一个自定义容器并使ListBox显示它。否则,只需将字符串添加到ListBox并在需要时使用其项目索引来访问容器。 –