为什么这种发布不起作用?

时间:2010-05-22 14:08:07

标签: iphone objective-c xcode memory-management

我有一个关于以下内容的新手问题:

- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section {
    NSArray *anArray;
    anArray = [dictionary objectForKey: [NSString stringWithFormat:@"%d", section]];
    //here dictionary is of type NSDictionary, initialized in another place.
    AnObject *obj = [[AnObject alloc] init];
    obj = [anArray objectAtIndex:0];
    [anArray release];
    return obj.title;
}

如果我按原样运行它,我会收到错误。 如果我不放[anArray发布]它就可以了。 我不太明白为什么会这样?

感谢。

3 个答案:

答案 0 :(得分:2)

你绝对必须阅读并理解 Cocoa Memory Management Rules,特别是声明的基本规则:

  

如果使用名称以“alloc”或“new”开头或包含“copy”(例如,alloc,newObject或mutableCopy)的方法创建对象,或者如果发送它,则获取对象的所有权保留信息。您有责任使用release或autorelease放弃您拥有的对象的所有权。在您收到对象的任何其他时间,您必须释放它。

现在,看看你是如何掌握anArray的。您使用了方法objectForKey:它不是以alloc开头,也不是new,也不包含copy。你也没有留下一个阵容。因此,您不拥有anArray。你不能释放它。

上面引用的规则是关于在iPhone或Mac上使用Cocoa进行编程而不进行垃圾回收的最重要的事情。其中一张海报出现了首字母缩略词NARC(New Alloc Retain Copy)作为备忘录,非常方便。

让我们将规则应用于代码中名为obj的变量。你通过调用alloc获得了它,因此你有责任释放它。但是,然后通过调用objectForIndex再次获取它(覆盖前一个值):所以在此之后你不能释放它。然而,第一个值确实需要释放,现在已经泄露。事实上,分配线是不必要的。

答案 1 :(得分:1)

您不需要释放anArray,因为您没有创建它。这本词典只是给你一个指向它的指针。

在您创建AnObject时,您会看到内存泄漏。在下一行,您将变量“obj”重新分配为您从anArray获得的内容。但是你还没有发布你在上面一行创建的AnObject。

我认为您的代码应如下所示:

- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section {
    NSArray *anArray;
    anArray = [dictionary objectForKey: [NSString stringWithFormat:@"%d", section]];
    //here dictionary is of type NSDictionary, initialized in another place.
    obj = [anArray objectAtIndex:0];
    return obj.title;
}

您无需发布尚未创建的内容。

答案 2 :(得分:1)

anArray未被您分配,保留,复制或更新,因此您无需发布它。

此外,您在使用alloc / init创建全新AnObject实例时会发生泄漏,但之后会直接从数组中为其分配新值。

您的代码应如下所示:

- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section {
    NSArray *anArray;
    anArray = [dictionary objectForKey: [NSString stringWithFormat:@"%d", section]];
    //here dictionary is of type NSDictionary, initialized in another place.
    AnObject *obj = [anArray objectAtIndex:0];
    return obj.title;
}