Свойства цели C 2.0 и «сохранить» - PullRequest
1 голос
/ 12 марта 2010

Глупый вопрос, но почему мы должны использовать 'retain' при объявлении свойства? Разве он не сохраняется в любом случае, когда ему назначается что-то?

Глядя на этот пример, кажется, что объект автоматически сохраняется при распределении, так какой смысл?

#import "Fraction.h"
#import <stdio.h>

int main( int argc, const char *argv[] ) {
    Fraction *frac1 = [[Fraction alloc] init];
    Fraction *frac2 = [[Fraction alloc] init];

    // print current counts
    printf( "Fraction 1 retain count: %i\n", [frac1 retainCount] );
    printf( "Fraction 2 retain count: %i\n", [frac2 retainCount] );

    // increment them
    [frac1 retain]; // 2
    [frac1 retain]; // 3
    [frac2 retain]; // 2

    // print current counts
    printf( "Fraction 1 retain count: %i\n", [frac1 retainCount] );
    printf( "Fraction 2 retain count: %i\n", [frac2 retainCount] );

    // decrement
    [frac1 release]; // 2
    [frac2 release]; // 1

    // print current counts
    printf( "Fraction 1 retain count: %i\n", [frac1 retainCount] );
    printf( "Fraction 2 retain count: %i\n", [frac2 retainCount] );

    // release them until they dealloc themselves
    [frac1 release]; // 1
    [frac1 release]; // 0
    [frac2 release]; // 0

■ выход

Количество фракций 1: 1

Количество фракций 2: 1

Количество фракций 1: 3

Количество фракций 2: 2

Количество фракций 1: 2

Количество фракций 2: 1

делалирующая фракция

делалирующая фракция


Это сводит меня с ума!

1 Ответ

3 голосов
/ 12 марта 2010

Поведение свойства по умолчанию - ASSIGN, а не RETAIN. Это не одно и то же поведение. Если ваше свойство для примитивного типа данных, такого как int, тогда ASSIGN будет правильным для использования. Однако, если вы укажете (сохраните) и свойство будет указывать на указатель объекта, такой как объект NSObject *, указателю будет назначен адрес памяти объекта, и его счетчик приращений увеличивается на единицу. Если ваша программа состоит только из одной основной функции, то ее цель трудно увидеть. Однако предположим, что у вашего класса был этот метод:

-(void)setMyArrayWithString:(NSString *)s{
    myArray = [NSArray arrayWithObject:s];
    }

Предположим, что myArray определен как NSArray * myArray и имеет правильный оператор @property (retain). Все работает нормально, пока метод не вернется. Это связано с тем, что объект, возвращаемый из NSArray, является автоматически выпущенным объектом. Если мы не сохраним его, он будет выпущен NSAutoReleasePool, и мы не сможем его использовать (и мы получим неприятные ошибки и нарушения прав доступа). Чтобы исправить это, мы можем сделать одну из двух вещей:

-(void)setMyArrayWithString:(NSString *)s{
    self.myArray = [NSArray arrayWithObject:s];
// OR
    myArray = [[NSArray arrayWithObject:s] retain];    
}

Первое решение использует self.myArray для использования определения @property. Этот код присваивает, а затем сохраняет объект, чтобы мы не потеряли его при возврате из функции. Второе решение устанавливает указатель NSArray * myArray вручную, а затем вручную сохраняет объект NSArray. В любом случае NSAutoreleasePool освободит объект в конце функции, однако он не будет освобожден, потому что у нас все еще есть наше удержание от более раннего сохранения его.

...