Objective C: почему выпуск сразу после создания объекта пользовательского интерфейса

Когда Вы выпускаете сообщение об ошибке, по крайней мере, пытаетесь предоставить ту же информацию, программа имела, когда это приняло решение бросить ошибку.

"Разрешение, отклоненное", говорит Вам, что была проблема разрешения, но Вы понятия не имеете, почему или где проблема произошла. "Не может транзакция записи регистрировать/my/file: файловая система только для чтения", по крайней мере, сообщает основание, о котором было принято решение, даже если неправильно - особенно, если это неправильно: неправильное имя файла? открытый неправильно? другая неожиданная ошибка? - и сообщает, где Вы были, когда у Вас была проблема.

5
задан Matthew Chen 6 September 2009 в 19:55
поделиться

4 ответа

Не думайте, что сохранить / релиз просто как нечто, что нужно сбалансировать. Они передают право собственности. Поймите идею владения, и вы поймете управление памятью в Какао.

Владение устанавливается в областях; область действия метода, область экземпляра объекта или глобальная область приложения. Методы владеют , сохраняя локальные переменные. Экземпляры объекта владеют , имея сохраненную переменную экземпляра. А приложение владеет , имея сохраненную глобальную переменную.

Текущий метод владеет объектом, если вы получили его из вызова метода с именем alloc , или содержит слово new или copy (Как в newSprocket или mutableCopy ) . Все объекты, предоставленные вам другими способами, не принадлежат вам, например, аргументы вашего метода или результат формируют большинство вызовов методов.

Вы можете получить доступ к экземплярам объектов, которыми вы не владеете, вы делаете это все время как . Вам нужно только явно взять на себя ответственность с сохранить , если вы хотите, чтобы экземпляр объекта жил после выполнения текущего метода (или цикла выполнения, если вы хотите быть придирчивым) .

Эта строка кода становится владельцем экземпляра объекта, на который ссылается локальная переменная contentView . Метод loadView теперь владеет объектом.

UIView *contentView = [[UIView alloc] initWithFrame:applicationFrame];

Затем экземпляр объекта self становится владельцем, потому что свойство объявлено как сохраненное. У экземпляра объекта теперь есть два владельца: метод и класс.

self.view = contentView;

С этого момента мы никогда не получаем доступ к объекту представления через локальную переменную в этом методе. Метод больше не нуждается в этом, и поэтому он отказывается от владения. Теперь объект принадлежит только экземпляру объекта и больше не является проблемой для этого метода.

[contentView release];
6
ответ дан 18 December 2019 в 05:36
поделиться

Олбаум прав, говоря, что self.view = contentView; сохранит ваше представление, что означает, что оно не будет освобождено. Однако такое поведение не всегда будет иметь место:

Если вы посмотрите в документации (или заголовке) для UIViewController, вы увидите, что свойство view объявлено следующим образом:

@property(nonatomic, retain) UIView *view;

Это означает, что всякий раз, когда устанавливается свойство представления ( foo.view = anotherView или [foo setView: anotherView]; ), другое представление будет сохранено. Если свойство представления было объявлено как:

@property(nonatomic, assign) UIView *view;

, то представление , а не было бы сохранено. Он будет выполнять простое присвоение указателя переменной экземпляра. В этом случае, вы будете правы, если последующий выпуск от до contentView уничтожит представление, что означает, что у контроллера будет устаревший указатель, а это значит, что ваше приложение, вероятно, выйдет из строя.

В другом случае слова, когда вы используете свойства, убедитесь, что вы знаете, сохраняют или присваивают . (Если нет, то это назначить ). Затем соответствующим образом управляйте своей памятью.

13
ответ дан 18 December 2019 в 05:36
поделиться

Нет, потому что self.view = contentView сохранит его. А так как вы должны сбалансировать удержание и освобождение вызовов, вам необходимо освободить его, чтобы сбалансировать выделение.

8
ответ дан 18 December 2019 в 05:36
поделиться

Если вы привыкли к другим языкам, было бы естественно взглянуть на self.view = contentView и подумать: «О, это назначение переменной экземпляра». Но это не так - переменные экземпляра не могут быть назначены с помощью точки, потому что объекты в Objective-C всегда являются указателями. Это свойство доступа. В большинстве случаев это в точности эквивалентно записи [self setView: contentView] .

В большинстве случаев этот метод установки будет реализован примерно так:

- (void)setView:(UIView *)view {
    if (view != _view) {
        [_view release]; // where _view is the name of the actual instance variable
        _view = [view retain];
    }
}

В таком случае он сохраняется при установке свойства. Таким образом, вы должны освободить его там, иначе первоначальное право собственности, вызванное выделением объекта, никогда не будет освобождено.

5
ответ дан 18 December 2019 в 05:36
поделиться