简体   繁体   English

可可粉:什么释放,什么时候释放?

[英]Cocoa Touch: What to release, when to release it?

I'm trying hard to understand when and what I must relase in Cocoa Touch as it doesn't have garbage collection. 我正在努力了解何时和在Cocoa Touch中必须释放什么,因为它没有垃圾收集。

This code block is from apples iphone sample PeriodicElements and they release anElement and rawElementArray but not thePath, firstLetter, existingArray and tempArray? 此代码块来自苹果iphone示例PeriodicElements,它们释放anElement和rawElementArray,但不释放Path,firstLetter,existedArray和tempArray吗?

I would have thought that at least tempArray and existingArray should be released. 我本以为至少应该释放tempArray和existingArray。

Could some brainy person please explain to me why? 有头脑的人可以向我解释为什么吗?

Thanks :) 谢谢 :)

- (void)setupElementsArray {
NSDictionary *eachElement;

// create dictionaries that contain the arrays of element data indexed by
// name
self.elementsDictionary = [NSMutableDictionary dictionary];
// physical state
self.statesDictionary = [NSMutableDictionary dictionary];
// unique first characters (for the Name index table)
self.nameIndexesDictionary = [NSMutableDictionary dictionary];

// create empty array entries in the states Dictionary or each physical state
[statesDictionary setObject:[NSMutableArray array] forKey:@"Solid"];
[statesDictionary setObject:[NSMutableArray array] forKey:@"Liquid"];
[statesDictionary setObject:[NSMutableArray array] forKey:@"Gas"];
[statesDictionary setObject:[NSMutableArray array] forKey:@"Artificial"];

// read the element data from the plist
NSString *thePath = [[NSBundle mainBundle]  pathForResource:@"Elements" ofType:@"plist"];
NSArray *rawElementsArray = [[NSArray alloc] initWithContentsOfFile:thePath];

// iterate over the values in the raw elements dictionary
for (eachElement in rawElementsArray)
{
    // create an atomic element instance for each
    AtomicElement *anElement = [[AtomicElement alloc] initWithDictionary:eachElement];

    // store that item in the elements dictionary with the name as the key
    [elementsDictionary setObject:anElement forKey:anElement.name];

    // add that element to the appropriate array in the physical state dictionary 
    [[statesDictionary objectForKey:anElement.state] addObject:anElement];

    // get the element's initial letter
    NSString *firstLetter = [anElement.name substringToIndex:1];
    NSMutableArray *existingArray;

    // if an array already exists in the name index dictionary
    // simply add the element to it, otherwise create an array
    // and add it to the name index dictionary with the letter as the key
    if (existingArray = [nameIndexesDictionary valueForKey:firstLetter]) 
    {
    [existingArray addObject:anElement];
    } else {
        NSMutableArray *tempArray = [NSMutableArray array];
        [nameIndexesDictionary setObject:tempArray forKey:firstLetter];
        [tempArray addObject:anElement];
    }

    // release the element, it is held by the various collections
    [anElement release];

}
// release the raw element data
[rawElementsArray release];



// create the dictionary containing the possible element states
// and presort the states data
self.elementPhysicalStatesArray = [NSArray arrayWithObjects:@"Solid",@"Liquid",@"Gas",@"Artificial",nil];
[self presortElementsByPhysicalState];

// presort the dictionaries now
// this could be done the first time they are requested instead

[self presortElementInitialLetterIndexes];

self.elementsSortedByNumber = [self presortElementsByNumber];
self.elementsSortedBySymbol = [self presortElementsBySymbol];

} }

They create rawElementsArray by sending +alloc to the class, therefore this object is owned by the code in the sample above and must be released. 他们通过向类发送+alloc来创建rawElementsArray ,因此,该对象由上述示例中的代码拥有,必须释放。 Similarly with anElement . anElement类似。 Note that thePath and tempArray are not created by sending +alloc , +new or -copy messages, therefore the calling code is not responsible for the lifetime of those objects. 注意, thePathtempArray不是通过发送+alloc+new-copy消息来创建的,因此调用代码对这些对象的生存期不承担任何责任。 Please have a look at this collection of Cocoa memory management articles: 请查看以下可可内存管理文章集:

http://iamleeg.blogspot.com/2008/12/cocoa-memory-management.html http://iamleeg.blogspot.com/2008/12/cocoa-memory-management.html

The reason you don't have to release tempArray is because it's been allocated and then autoreleased right away. 不必释放tempArray的原因是因为它已被分配,然后立即自动释放。 Autorelease is a method of scheduling a release call sometime in the future, so that the caller of an API doesn't have to do any explicit releasing of the result. 自动释放是一种在将来某个时间安排释放调用的方法,因此API的调用者不必对结果进行任何显式释放。

Matt Dillard has provided a detailed explanation of Objective C's memory management strategy and has explained it much better than I can. 马特·迪拉德(Matt Dillard)详细介绍了Objective C的内存管理策略,并且比我能更好地解释了它。

The convention is that when you create an object using a class method it should have been autoreleased. 约定是,当您使用类方法创建对象时,该对象应已自动释放。 This means that at the end of the run loop when the autorelease pool is flushed these objects will be released. 这意味着在运行循环结束时,刷新自动释放池后,这些对象将被释放。 However, if you create something using +alloc] -init] or -copy, -mutableCopy or +new (which is the same as +alloc] -init]) then it will not have been autoreleased. 但是,如果您使用+ alloc] -init]或-copy,-mutableCopy或+ new(与+ alloc] -init]相同)来创建内容,则不会将其自动释放。

For example: 例如:

NSArray *array1 = [NSArray arrayWithObject:@"foo"];
NSArray *array2 = [[NSArray alloc] initWithObject:@"foo"];

Array1 will be autoreleased and you don't need to worry about it. Array1将自动释放,您无需担心。 Array2 will need to be manually released. Array2将需要手动释放。 Or alternatively you could do: 或者,您可以执行以下操作:

NSArray *array2 = [[[NSArray alloc] initWithObject:@"foo"] autorelease];

Which is pretty much what +arrayWithObject: does. + arrayWithObject:几乎可以做到这一点。

Of course this leads to an important consideration with the lifetime of instance variables. 当然,这导致需要对实例变量的生存期进行重要考虑。 If you create the instance variable as with array2 then it will be fine as it has a retain count of 1. However, array1 will need to be retained otherwise it will be autoreleased at the end of the runloop, giving it a retain count of 0 and so it will be freed and you will be left with a dangling pointer. 如果您与array2一样创建实例变量,则它的保留计数为1会很好。但是,必须保留array1,否则它将在runloop的结尾自动释放,使其保留计数为0因此它将被释放,并且您将剩下一个悬空的指针。

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

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