简体   繁体   English

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

[英]Why this kind of release doesn't work?

I have a newbie question about the following: 我有一个关于以下方面的新手问题:

- (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;
}

If I run it as it is I will get an error. 如果我按原样运行,则会收到错误消息。 If I don't put [anArray release] it works just fine. 如果我不输入[anArray版本],则效果很好。 I don't quite understand why is this happening? 我不太明白为什么会这样?

Thanks. 谢谢。

You absolutely must read and understand the Cocoa Memory Management Rules , in particular the fundamental rule which states: 您绝对必须阅读并理解 Cocoa内存管理规则 ,尤其是指出以下内容的基本规则:

You take ownership of an object if you create it using a method whose name begins with “alloc” or “new” or contains “copy” (for example, alloc, newObject, or mutableCopy), or if you send it a retain message. 如果使用名称以“ alloc”或“ new”开头或包含“ copy”(例如alloc,newObject或mutableCopy)的方法创建对象,或者向其发送保留消息,则您拥有该对象的所有权。 You are responsible for relinquishing ownership of objects you own using release or autorelease. 您有责任使用release或autorelease放弃您拥有的对象的所有权。 Any other time you receive an object, you must not release it. 任何其他时间收到对象时,都不得释放它。

Now, look at how you got hold of anArray. 现在,看看如何掌握anArray。 You used the method objectForKey: It does not start with alloc, nor new, nor does it contain copy. 您使用了方法objectForKey:它不以alloc开头,也不是new,也不包含副本。 Nor have you retained anArray. 您也没有保留anArray。 Therefore, you do not own anArray. 因此,您不拥有anArray。 You must not release it. 您不得释放它。

The above quoted rule is the most important thing to know about programming with Cocoa on the iPhone or Mac without garbage collection. 上面引用的规则是有关在不进行垃圾回收的情况下在iPhone或Mac上使用Cocoa进行编程的最重要的知识。 One of the other posters here came up with the acronym NARC (New Alloc Retain Copy) as an aide memoire which is quite handy. 这里的其他海报之一是首字母缩略词NARC(新Alloc保留副本)作为辅助备忘录,非常方便。

Let's apply the rule to the variable called obj in your code. 让我们将规则应用于代码中名为obj的变量。 You obtained that with a call to alloc, therefore you are responsible for releasing it. 您是通过调用alloc获得的,因此您有责任释放它。 However, you then obtained it again (overwriting the previous value) with a call to objectForIndex: so after this you must not release it. 但是,然后通过调用objectForIndex再次获得它(覆盖先前的值):因此在此之后,您不能释放它。 However, the first value did need releasing and has now leaked. 但是,第一个值确实需要释放,现在已经泄漏。 in fact, the alloc line is unnecessary. 实际上,分配行是不必要的。

You don't need to release anArray because you are not creating it. 您不需要释放anArray,因为您没有创建它。 The dictionary is just giving you a pointer to the one it has. 字典只是给您一个指向它的指针。

You do, it appears, have a memory leak where you create the AnObject. 您这样做,似乎在创建AnObject时发生了内存泄漏。 On the next line you reassign the variable "obj" to be something you get from anArray. 在下一行中,将变量“ obj”重新分配为从anArray获得的变量。 But you have not released the AnObject you created on the line above. 但是您尚未释放在上一行创建的AnObject。

I think your code should look like this: 我认为您的代码应如下所示:

- (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;
}

You don't need to release what you have not created. 您无需释放尚未创建的内容。

anArray is not allocated, retained, copied or new'd by you, so you don't need to release it. anArray不是由您分配,保留,复制或新增的,因此您无需释放它。

Also, you have a leak where you create a brand new AnObject instance using alloc/init, but then assign a new value to it straight after, from the array. 另外,您还有一个泄漏,您在其中使用alloc / init创建一个全新的AnObject实例,然后从数组中直接为其分配一个新值。

Your code should look like: 您的代码应如下所示:

- (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;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM