保留NSArray中的元素

时间:2012-06-14 12:13:08

标签: objective-c ios cocoa-touch memory-management

我按以下方式创建NSMutable数组:

-(NSArray*)createArrayFromString:(NSString*)str
{
    NSArray *arr = [str componentsSeparatedByString:@" "]; 
    NSMutableArray *result = [NSMutableArray arrayWithCapacity:[arr count]];

    for(NSString *s in arr){
        if([s length]>0){
            [result addObject:[s retain]];
        }
    }
    return (NSArray*) result;
}

这里是调用方法,它将接收到的数组元素放入Chapter对象的属性resRefs中:

-(Chapter*)createChapter:(CXMLNode*)node
    {
        Chapter *chapter = [[Chapter alloc] init];
        chapter._id = [[(CXMLElement*)node  attributeForName:@"id"] stringValue];
        chapter.title = [[(CXMLElement*)node attributeForName:@"title"] stringValue];
        chapter.text = [node stringValue];
        [chapter.pids addObjectsFromArray:[self createArrayFromString:[[(CXMLElement*)node attributeForName:@"pids"]stringValue]]];
        [chapter.resRefs addObjectsFromArray:[self createArrayFromString:[[(CXMLElement*)node attributeForName:@"resRefs"]stringValue]]];
        return chapter;
    }

以下是问题:

没有

中的保留调用
[result addObject:[s retain]];

我无法从ViewController访问NSString元素(EXC_BAD_ACCESS)

我是否正确使用保留在这里?

修改

已更改

 [[result addObject:s] retain];

 [result addObject:[s retain]];

第二行最初是在我的代码中。 发布此问题后删除保留并将其重新插入错误的位置。 尽管如此,保留在这里是有效的,而将它留下来并不是没有。

编辑2:

发现了分析仪(CMD + SHIFT + B),发现了几个内存泄漏, 删除它们,EXC_BAD_ACCESS消失了。 感谢各位的帮助!

3 个答案:

答案 0 :(得分:8)

[result addObject:s]

什么都不返回,所以没有什么可以保留的。

对象被数组保留。

NSMutableArray *result = [NSMutableArray arrayWithCapacity:[arr count]];

不会被保留,也不应该保留,因为它是本地对象。

您应该熟悉memory rules。命名约定说,名称以“alloc”,“new”,“copy”或“mutableCopy”开头的方法必须提供一个retaind对象。所以你的方法似乎没问题,因为它不会从任何一个开始,并返回一个自动释放(=未保留)的对象。这是打电话的责任,保留与否。

还附注:

return (NSArray*) result;

不会将您的NSMutableArray转换为NSArray。演员表只告诉编译器它应该期待什么。由于NSMutableArray是一个NSArray,编译器已经知道了。实际上,转换已经由方法签名中的返回定义定义。


你在方法中做了些什么吗?如果不是 - 我不想让你感到苦恼 - 你真的不需要它,因为NSArray *arr = [str componentsSeparatedByString:@" "];只是做你想要的。如果您确实希望@" "远离来电者,则应考虑在NSString componentsSeparatedByBlank上使用名为@interface NSString (Separation) -(NSArray *)componentsSeparatedByBlank; @end @implementation NSString (Separation) -(NSArray *)componentsSeparatedByBlank { return [self componentsSeparatedByString:@" "]; } @end 的{​​{1}}。

它可能看起来像

-(NSArray *)componentsSeparatedByWhiteSpace
{
    NSArray *array = [self componentsSeparatedByCharactersInSet: [NSCharacterSet whitespaceCharacterSet]];
    return [array filteredArrayUsingPredicate: [NSPredicate predicateWithFormat:@"SELF != ''"]];
}

或使用空格字符集:

{{1}}

答案 1 :(得分:3)

  

我是否正确使用保留在这里?

没有。 NSMutableArray保留您添加到其中的对象。然后,当您调用remove或数组被dealloc'd时,它会释放它们。您无需在此处致电保留。但是,这不是您遇到EXC_BAD_ACCESS

的原因

正如vikingosegundo所说,addObject不会返回任何内容,因此在其上调用retain会为您提供EXC_BAD_ACCESS。

您尝试执行的操作的正确语法是(注意:如上所述,无需执行此操作)

[result addObject:[s retain]]; // BAD

所以,总之,只是

[result addObject:s]; // GOOD - s is retained by result

编辑*改写海报原始代码......

-(NSArray*)arrayFromString:(NSString*)str // Note naming convention of method
{
    NSMutableArray *arr = [str componentsSeparatedByString:@" "]; // Won't give you any 0 length strings

// Do some other character/validation checks here?

    return arr; // returns autoreleased NSMutableArray complying to naming convention
}

如果您在返回之前不想对字符串执行任何操作,则可以在createChapters方法中使用它...

NSArray *arr = [[[(CXMLElement*)node attributeForName:@"pids"] stringValue] componentsSeparatedByString:@" "];
[chapter.pids addObjectsFromArray:arr];

请阅读内存管理和命名约定,将来会为您节省大量时间。

答案 2 :(得分:2)

[[result addObject:s] retain]; 

是一种无效方法。这意味着它不会返回任何值,如:

- (NSString)methodThatReturnsString;

会。你保留了一个空洞,它没有保留任何东西,因为虚空基本上没有任何意义。但是,添加数组的对象将由数组保留。