向NSMutableArray添加多个NSObject对象

3
使用以下代码后,数组中的两个项都是相同的(即最后一项)。我做错了什么,导致这个数组覆盖了这些值?我想使用一个对象,这样我就不必实例化X个对象。
self.myArray = [[NSMutableArray alloc] init];

MyObjClass *obj = [[MyObjClass alloc] init];
obj.firstName = @"First Name";
obj.lastName = @"Last Name";
obj.created = @"Dec 17 16:24";
[self.myArray addObject:obj];

obj.firstName = @"First Name2";
obj.lastName = @"Last Name2";
obj.created = @"Dec 18 7:41";
[self.myArray addObject:obj];

MyObjClass.h 中,我有 @interface MyObjClass : NSObject。这里的 NSObject 是否为错误的数据类型? MyObjClass.h 中的属性:
@property (strong) NSString *firstName;
@property (strong) NSString *lastName;

以下是来自MyObjClass.m的代码:

@synthesize firstName, lastName;
5个回答

4
数组并没有覆盖值,是你在代码中的问题。你只有一个 MyObjClass 的实例。*obj 是指向该对象的指针,当你将其两次添加到数组中时,数组有两个索引指向你两次添加的对象。
通过设置 obj 上的属性,你正在更改 *obj 指针和数组都指向的同一个对象的值。
为什么你关心实例化 X 个对象?这听起来像是你想要数组中有具有不同值的 X 个对象。
除了创建 X 个对象外,你还可以复制第一个对象,设置值然后将其添加到数组中,但由于你已经设置了所有值,我不确定为什么你不只是初始化一个新对象。
编辑:
根据你下面的评论,看起来你对多个对象的担忧在于内存管理。当你将对象添加到数组中时,它会保留该对象,因此在将其添加后(如果你在该范围内已经使用完它),请释放或自动释放它。当数组被释放时,它将调用数组中所有对象的释放函数。无论你是通过初始化还是复制,你都需要 n 个对象 - 你仍然有多个对象。释放它们,然后让数组在其释放时进行释放。

我每次都必须使用唯一的对象吗?是否可以重新设计此代码,使其可以仅使用一个对象运行?如果我使用多个对象,如何在将它们添加到数组后释放它们的内存? - jwhat

1

您需要为每个添加的对象创建一个唯一的实例。此外,由于将其添加到数组中会使其保留,因此在此方法中需要释放obj。但是,如果您使用ARC,则不需要/允许释放。

self.myArray = [[NSMutableArray alloc] init];

MyObjClass *obj;

obj = [[[MyObjClass alloc] init] autorelease];
obj.firstName = @"First Name";
obj.lastName = @"Last Name";
obj.created = @"Dec 17 16:24";
[self.myArray addObject:obj];

obj = [[[MyObjClass alloc] init] autorelease];
obj.firstName = @"First Name2";
obj.lastName = @"Last Name2";
obj.created = @"Dec 18 7:41";
[self.myArray addObject:obj];

iOS5中已经没有自动释放池了。我不确定现在是否会自动处理... - jwhat
2
不是iOS5甚至iOS4的问题,而是基于ARC的项目(实际上是文件)不允许使用autorelease、release或retain。并非每个人都出于各种原因在使用ARC。 - zaph

1
你误解了 -addObject: 方法和对象的概念。你是在将指向 MyObjClass 实例的引用(指针)添加到数组中。如果你两次添加同一个实例,这并没有什么区别。而且,由于你只在数组中存储了对象的指针,所以你总是拥有数组中最新的“版本”对象。
你需要分配两个实例并将它们都添加进去:
MyObjClass *object1 = ...;
[array addObject:object1];
MyObjClass *object2 = ...;
[array addObject:object2];

0

NSMutableArray 添加对象时,它们将被保留而不是复制。如果您不想修改所包含的对象,请使用以下代码序列:

self.myArray = [[NSMutableArray alloc] init];

MyObjClass *obj = [[MyObjClass alloc] init];
obj.firstName = @"First Name";
obj.lastName = @"Last Name";
obj.created = @"Dec 17 16:24";
[self.myArray addObject:[[obj copy] autorelease]];

obj.firstName = @"First Name2";
obj.lastName = @"Last Name2";
obj.created = @"Dec 18 7:41";
[self.myArray addObject:obj]; // if you're using it further then you need to make a copy of it again

我无法在ARC中使用autorelease。只是省略autorelease是否安全,还是有一种新的不同方式来确保它从内存中释放?此外,使用[obj copy]会抛出此错误:未识别的选择器发送到实例 - jwhat
抱歉,我还没有研究过ARC。 - alex-i
无论如何,“copy”可能并不是一个好的选择,因为您正在覆盖所有先前的值,所以您可以创建一个新实例并添加它,而不是调用“copy, autorelease”(其他评论中有一些示例)。 - alex-i

0
尝试像这样设置您的MyObjClass类中的属性:
@property (copy) NSString *firstName;
@property (copy) NSString *lastName;
@property (copy) NSString *created;

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接