Cocoa Touch: что выпустить, когда его выпустить? - PullRequest
1 голос
/ 10 января 2009

Я изо всех сил пытаюсь понять, когда и что я должен рассказывать в Cocoa Touch, поскольку в нем нет сборки мусора.

Этот блок кода взят из примера PeriodicElements для iphone, и они выпускают anElement и rawElementArray, но не thePath, firstLetter, существующиеArray и tempArray?

Я бы подумал, что по крайней мере tempArray и существующий Array должны быть освобождены.

Может, какой-нибудь умник объяснит мне, почему?

Спасибо:)

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

}

Ответы [ 3 ]

4 голосов
/ 10 января 2009

Они создают rawElementsArray, отправляя +alloc классу, поэтому этот объект принадлежит коду в приведенном выше примере и должен быть освобожден. Аналогично с anElement. Обратите внимание, что thePath и tempArray не создаются путем отправки сообщений +alloc, +new или -copy, поэтому вызывающий код не несет ответственности за время жизни этих объектов. Пожалуйста, взгляните на этот сборник статей по управлению памятью Какао:

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

1 голос
/ 10 января 2009

Соглашение состоит в том, что когда вы создаете объект с использованием метода класса, он должен быть автоматически освобожден. Это означает, что в конце цикла выполнения при сбросе пула автоматического выпуска эти объекты будут освобождены. Однако, если вы создадите что-либо, используя + alloc] -init] или -copy, -mutableCopy или + new (что аналогично + alloc] -init]), это не будет автоматически выпущено.

Например:

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

Array1 будет автоматически выпущен, и вам не нужно об этом беспокоиться. Array2 необходимо будет разблокировать вручную. Или вы можете сделать:

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

Что в значительной степени делает + arrayWithObject:

Конечно, это приводит к важному рассмотрению времени жизни переменных экземпляра. Если вы создадите переменную экземпляра, как в случае с array2, то все будет в порядке, поскольку она имеет счет сохранения 1. Однако, массив1 нужно будет сохранить, иначе он будет автоматически освобожден в конце цикла выполнения, что даст ему счет сохранения 0 и поэтому он будет освобожден, и вы останетесь с висящим указателем.

1 голос
/ 10 января 2009

Причина, по которой вам не нужно выпускать tempArray, заключается в том, что он был выделен, а затем автоматически выпущен. Авторелиз - это метод планирования вызова релиза когда-нибудь в будущем, так что вызывающая сторона API не должна делать явного освобождения результата.

Мэтт Диллард дал подробное объяснение стратегии управления памятью в Objective C. и объяснил это гораздо лучше, чем я.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...