从具有NSArray返回值的方法返回NSMutableArray对象

时间:2014-02-11 16:24:43

标签: objective-c automatic-ref-counting

从使用NSArray动态构建数组的方法返回NSDictionary(或NSMutableArray等)时,执行此操作的标准方法是什么,并避免使用ARC时随机内存泄漏?

例如,假设我们有一些带有名称列表的类,我们想手动过滤并获取以给定字母开头的所有名称:

- (NSArray *)getNamesByFirstLetter:(NSString *)firstLetter 
{
    NSMutableArray *returnValue = [[NSMutableArray alloc] init];
    for(id item in self.names)
    {
        if([item hasPrefix:firstLetter])
        {
            [returnValue addObject:item];
        }
    }        
    return returnValue; // just return the above array
}

当谈到返回值时,我可以想到四种可能的方法:

  1. 直接返回NSMutableArray(如上所述)

    return returnValue;
    
  2. 返回copy

    return [returnValue copy];
    
  3. 使用NSArray arrayWithArray返回

    return [NSArray arrayWithArray:returnValue];
    
  4. 创建NSArray,手动将NSMutableArray设置为nil

    NSArray *temp = [NSArray arrayWithArray:returnValue]; // could use [returnValue copy] here too
    returnValue = nil;
    return temp;
    
  5. 当一个程序使用ARC时,这四种方法之间是否有任何真正的区别,还是仅归结为个人偏好?

    此外,除了可能的内存泄漏之外,使用一种方法而不是另一种方法还有其他影响吗?

    注意,如果这是重复的,请告诉我,我会把问题记下来。我尝试过搜索,但很难将问题缩小到几个搜索字词。

3 个答案:

答案 0 :(得分:9)

启用ARC后,所有四个选项都可以正常使用(即您提出的解决方案都不会导致内存泄漏)。

但是,您概述的4种解决方案略有不同。数字1将返回NSMutableArray,这可能不会导致问题,因为NSMutableArray将响应与NSArray相同的所有消息(但返回的对象将是可变的,您可能不会要)。

选项2和选项3&之间存在细微差别。 4(在ARC下相同)。如果returnValuenil,则选项2将返回nil,但选项3& 4将返回空NSArray。 (这两种行为都是可取的;你应该决定你希望这种方法的行为方式)。此外,-copy可能比+arrayWithArray更快。

我会选择2。

答案 1 :(得分:3)

首先要说的是:您讨论的所有方法都不会导致ARC下的内存泄漏。此外,第四种方法不要求您将returnValue设置为nil - 编译器足够聪明,可以自行处理returnValue。这使得第四个方法与第三个方法完全相同。

此外,在copy上调用returnValue与从其内容创建新数组相同,因此第二种方法与后两种方法相同。

这给我们留下了两种方法 - 第一种,第二种/第三种/第四种。它们之间的主要区别在于用户可以使用他从方法中获取的数组。第一种方法是让用户修改数组;最后三个没有。决定你更喜欢哪种行为取决于你。

答案 2 :(得分:0)

在给定示例中没有泄漏的一点是,每个人都知道NSArray 可能是可变的。如果您是方法调用的结果,那么无论您是复制它还是按原样使用它,都可以随时更改它。这就是为什么不可变属性通常被声明为副本而不是强大的原因。为该属性分配可变值将执行实际复制,并且分配不可变值很便宜。

tl; dr:只返回returnValue,没关系。