0

我正在通过以下方式创建一个 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 (EXC_BAD_ACCESS) 访问 NSString 元素

我在这里正确使用保留吗?

编辑:

改变了

 [[result addObject:s] retain];

进入

 [result addObject:[s retain]];

第二行最初在我的代码中。发布此问题时,删除了保留并将其插入错误的位置。尽管如此,在此处保留保留有效,而将其保留则无效。

编辑2:

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

4

3 回答 3

8
[result addObject:s]

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

对象 s 被数组保留。

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

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

您应该熟悉记忆规则。命名约定说,名称以“alloc”、“new”、“copy”或“mutableCopy”开头的方法必须传递一个保留对象。所以你的方法似乎很好,因为它不以任何一个开头,并返回一个自动释放(=未保留)的对象。保留与否是调用者的职责。

还有一个旁注:

return (NSArray*) result;

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


您是否在该方法中做其他事情?如果没有——我不想让你难过——你真的不需要它,就像NSArray *arr = [str componentsSeparatedByString:@" "];你想要的那样。如果您真的想将@" "远离呼叫者的因素考虑在内,您应该考虑使用一个名为的类别,例如.NSStringcomponentsSeparatedByBlank

它可能看起来像

@interface NSString (Separation)
-(NSArray *)componentsSeparatedByBlank;
@end

@implementation NSString (Separation)
-(NSArray *)componentsSeparatedByBlank
{
    return [self componentsSeparatedByString:@" "];
}
@end

或使用空格字符集:

-(NSArray *)componentsSeparatedByWhiteSpace
{
    NSArray *array = [self componentsSeparatedByCharactersInSet: [NSCharacterSet whitespaceCharacterSet]];
    return [array filteredArrayUsingPredicate: [NSPredicate predicateWithFormat:@"SELF != ''"]];
}
于 2012-06-14T12:14:51.567 回答
3

我在这里正确使用保留吗?

不会。 NSMutableArray 会保留您添加到其中的对象。然后,当您调用 remove 或数组被解除分配时,它会释放它们。你不需要在这里调用retain。但是,这不是您遇到 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];

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

于 2012-06-14T12:21:54.620 回答
2
[[result addObject:s] retain]; 

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

- (NSString)methodThatReturnsString;

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

于 2012-06-14T12:17:18.430 回答