为NSMutableArray设置属性的适当方法

时间:2011-03-26 23:07:13

标签: iphone objective-c cocoa cocoa-touch ios

我想要一个可变数组并通过属性设置它,这个替代是更好的,请解释原因。我有2个替代方案

 NSMutableArray *arrSubTitles_temp = [[NSMutableArray alloc] initWithObjects:    
 @"String 1",
 @"String 2",nil];
 self.arrSubTitles = arrSubTitles_temp;
 [arrSubTitles_temp release];

 NSArray *arrSubTitles_temp = [[NSArray alloc] initWithObjects:    
 @"String 1",
 @"String 2",nil];
 self.arrSubTitles = [arrSubTitles_temp mutableCopy];
 [arrSubTitles_temp release];

我猜第一个更好,因为self.arrSubTitles属性保留在.h中,所以(在第二个)mutableCopy方法将提供可变数组,但在这种情况下保留计数将为2。

哪种方法更可取,我应该在设置属性时使用retain。或仅指定。请建议。

非常感谢提前:)

3 个答案:

答案 0 :(得分:6)

  1. 使用retain作为属性属性,除非你有充分的理由不这样做(例如:retain会导致保留周期,它是原始的,你需要保证对象是不可变的,等等)
  2. 使用您发布的第一个示例,因为第二个示例会泄漏内存。

  3. 如果您使用assign作为属性属性,则第一个选项可能会崩溃:

    1. 分配数组(由您拥有)
    2. 分配给一个房产(仍归您所有)
    3. 发布(没有所有者,及时解除分配)
    4. 尝试访问属性值:崩溃(因为指针是陈旧的)
    5. 然而,第二个可行:

      1. 分配数组(+1所有者)
      2. 复制数组(原始:+1所有者,复制:+1所有者)
      3. 将副本分配到属性中(两者仍有+1所有者)
      4. 释放原始数组(它被取消分配,副本继续存在)
      5. 无论如何,拥有assign属性然后自己管理值的保留是非常不寻常的。它非常容易出错,并且将属性声明为retain并让生成的setter为您处理release / retain舞蹈更加简单。

答案 1 :(得分:3)

无论哪种方式都有问题,因为调用者必须提供可变数组。如果调用者曾经传递过一个不可变数组(因为任何使用KVC设置属性的东西都可以在没有编译器警告的情况下执行),你会发现自己在一个mutable-array属性中持有一个不可变数组,并且此后不久会尝试改变它,引起异常。

我做的是持有一个可变数组,我在init创建并在dealloc中释放,作为属性的值,将属性声明为@property(nonatomic, copy) NSArray *myArray,并实现{ {1}}向我的可变数组发送setMyArray:消息。在任何时候我都不会切换阵列;在我的对象的整个生命周期中,我独占并私有地拥有相同的可变数组。

setArray:的等效实现将释放数组并将setMyArray:变量设置为输入数组的myArray。唯一的区别是,这会在整个过程中创建并丢弃更多的数组。

使用这些解决方案中的任何一个,调用者都不需要担心它是否通过了一个可变或不可变的数组;酒店将始终做正确的事。通常情况下,来电者不需要代表我保留它。

请注意,mutableCopy生成的setter实现不会做正确的事情。它将@synthesize发送到输入数组,该数组将返回一个不可变的副本。这会更糟糕,因为即使调用者确实传入了一个可变数组,它也无法工作。您必须实现自定义copy访问器才能正确处理不可变和可变数组。

答案 2 :(得分:0)

将其设置为自动释放怎么样? NSMutableArray * arrSubTitles_temp = [[[NSMutableArray alloc] initWithObjects:
 @“String 1”,  @“String 2”,nil] autorelease];  self.arrSubTitles = arrSubTitles_temp;  [arrSubTitles_temp release];