Как сохранить сеттер с помощью @synthesize? - PullRequest
5 голосов
/ 13 октября 2010

У меня есть следующее в заголовке:

@property (nonatomic, retain) UIView *overlay;

И в реализации:

@synthesize overlay;

Тогда:

UIView *tempOverlay = [[UIView alloc] initWithFrame:CGRectMake(160.0f, 70.0f, 150.0f, 310.0f)];
self.overlay = tempOverlay;
[tempOverlay release];

Разве не tempOverlay переменная выше ненужной?Разве я не могу просто сделать:

self.overlay = [[UIView alloc] initWithFrame:CGRectMake(160.0f, 70.0f, 150.0f, 310.0f)];

Ответы [ 6 ]

11 голосов
/ 13 октября 2010

Синтезированный сохраненный сеттер выглядит так:

- (void)setValue: (id)newValue
{
    if (value != newValue)
    {
        [value release];
        value = newValue;
        [value retain];
    }
}

В вашем случае у вас есть два допустимых метода:

1) Создайте временную переменную, alloc / init (= retained),установите свойство, отпустите.

IView *tempOverlay = [[UIView alloc] initWithFrame:CGRectMake(160.0f, 70.0f, 150.0f, 310.0f)];
self.overlay = tempOverlay;
[tempOverlay release];

2) Без временной переменной, установите непосредственно на ivar.

overlay = [[UIView alloc] initWithFrame:CGRectMake(160.0f, 70.0f, 150.0f, 310.0f)];

ОБНОВЛЕНИЕ: Если вы используете метод 2), вам нужно явно обработатьуправление остальной памятью (не только сохранение), освобождая любое предыдущее значение, которое оно может иметь раньше, если это необходимо.Если это делается только один раз в init (например), вы можете просто вставить [overlay release]; в dealloc.

2 голосов
/ 13 октября 2010

Использование атрибута retain указывает, что retain должен быть вызван для нового объекта, а предыдущее значение отправлено release.

Так, во втором блоке кода счетчик сохраненияобъект станет 2, так как вы больше не отпускаете его, а установщик сохраняет его.Это вряд ли то, что вы хотите.

1 голос
/ 13 октября 2010

Поскольку ваше свойство определяется с помощью (сохранения) любого экземпляра, установленного вами с помощью синтезированного установщика (с помощью синтаксиса self.overlay), автоматически будет отправлено сообщение сохранения:

// You're alloc'ing and init'ing an object instance, which returns an 
// instance with a retainCount of 1.
UIView *tempOverlay = [[UIView alloc] initWithFrame:CGRectMake(160.0f, 70.0f, 150.0f, 310.0f)];

// The overlay property is defined with (retain), so when you assign the new 
// instance to this property, it'll automatically invoke the synthesized setter, 
// which will send it a retain message. Your instance now has a retain count of 2.
self.overlay = tempOverlay;

// Send a release message, dropping the retain count to 1.
[tempOverlay release];

Если бы вы сделали:

self.overlay = [[UIView alloc] initWithFrame:CGRectMake(160.0f, 70.0f, 150.0f, 310.0f)];

У вашего оверлея будет количество отсчетов, равное двум, что, вероятно, приведет к утечке в какой-то момент в вашем приложении.

1 голос
/ 13 октября 2010

Если вы присваиваете объект непосредственно свойству, вы все равно должны его освободить:

self.overlay = [[[UIView alloc] initWithFrame:CGRectMake(160.0f, 70.0f, 150.0f, 310.0f)] autorelease];
0 голосов
/ 14 октября 2010

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

- (id)initWithStyle:(UITableViewStyle)style {
    if ((self = [super initWithStyle:style])) {
        NSLog(@"count: %d", [overlay retainCount]);
        self.overlay = [[UIView alloc] initWithFrame:CGRectMake(160.0f, 70.0f, 150.0f, 310.0f)];
        NSLog(@"count: %d", [overlay retainCount]);
        [overlay release]; NSLog(@"released once");
        NSLog(@"count: %d", [overlay retainCount]);     
        [overlay release]; NSLog(@"released twice");
        NSLog(@"count: %d", [overlay retainCount]);
    }
    return self;
}

Я получил следующий вывод консоли:

  • Иногда все шло нормально:

    count: 0
    count: 2
    released once
    count: 1
    released twice
    count: 1
    
  • В других случаях он падал:

    count: 0
    count: 2
    released once
    count: 1
    released twice
    Program received signal:  “EXC_BAD_ACCESS”.
    

Я знаю, что метод с использованием tempOverlay является правильным. Это кажется таким громоздким, но я предпочитаю autorelease, потому что я не понимаю, как работает autorelease или когда он вызывается Одно можно сказать наверняка. Приведенный выше код неверен, потому что я не хочу, чтобы у overlay было 2 счетчика хранения.

Странно то, что я не могу выпустить его дважды. Даже если он не падает, количество сохраняемых данных не уменьшается.

В любом случае, думаю, сейчас я буду придерживаться tempOverlay.

0 голосов
/ 13 октября 2010

Да, вы можете напрямую назначить вновь созданный объект объекту overlay. Если вы хотите, вы можете доказать это себе, распечатав счет сохранения объекта

NSLog(@"count: %d", [overlay retainCount]);
...