RAII в шаблоне Objective-C? - PullRequest
4 голосов
/ 08 декабря 2011

Я пишу код, подобный этому, для достижения безопасного кода исключений:

Container* container = [Container new];
@try {
    while(someCondition) {
        ElementType* value = [someObject createObjectFromStorage];
        [container add:value]; // container retains object
        [value release];
    }

    [_container release];
    _container = [container retain];
} @finally {
    [container release];
}

Есть ли какой-то другой, более краткий шаблон, которым нужно следовать в Objective-C?

Ответы [ 2 ]

8 голосов
/ 08 декабря 2011

Если вы просто хотите убедиться, что вы выпустили свои объекты, autorelease, вероятно, достаточно.Вы могли бы также взглянуть на новую опцию автоматического подсчета ссылок в Xcode 4.2.

Objective-C, как правило, не поддается RAII, поскольку все объекты Objective-C размещаются в куче.Это означает, что время жизни объектов не привязано явно к какому-либо конкретному кадру стека, и, таким образом, вы не можете полагаться на освобождение объекта в конце метода, который его выделил.

YouТакже следует помнить, что платформы Какао используют исключения только для указания ошибки программиста, а не ожидаемой ошибки.Из документации Apple по Exception Programming :

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

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

Фактически, поскольку исключения предназначены для использования только для исключительных ситуаций.В некоторых случаях по умолчанию недавно введенный автоматический подсчет ссылок будет преднамеренно пропускать объекты при возникновении исключения:

Стандартное соглашение Какао состоит в том, что исключения сигнализируют об ошибке программиста и не предназначены длявыздоровел от.Обеспечение безопасности исключений в коде по умолчанию наложило бы серьезные ограничения на время выполнения и размер кода на код, который обычно не заботится о безопасности исключений.Поэтому сгенерированный ARC код по умолчанию протекает при исключениях, что вполне нормально, если процесс все равно будет немедленно завершен.Программы, которые заботятся о восстановлении после исключений, должны включить эту опцию.

Программирование с помощью фреймворков Cocoa будет намного лучше, если вы будете придерживаться идиом этого фреймворка.Это означает использование исключений только для ошибок программиста и обработку ожидаемых ошибок времени выполнения с помощью NSError.Большинство программистов Какао никогда не беспокоятся о написании кода, исключающего исключения, потому что их код не генерирует исключения в первую очередь.Вы можете преуспеть, чтобы последовать их примеру.

1 голос
/ 08 декабря 2011

Авто-релиз является стандартным шаблоном.

Container* container = [[Container new] autorelease];
while(someCondition) {
    ElementType* value = [someObject createObjectFromStorage];
    [container add:value]; // container retains object
    [value release];
}

[_container release];
_container = [container retain];

Однако это относится только к управлению памятью;это не полная замена RAII.В Objective-C нет общепринятого шаблона, полностью заменяющего RAII, хотя вы могли бы создать такой шаблон в собственной кодовой базе, используя блоки (или, может быть, __attribute__((cleanup))).

Пока мыКстати, о шаблонах ... общий шаблон заключается в том, что любой метод, который не начинается со слова new, alloc, copy или mutableCopy, возвращает объект с автоматическим освобождением.Если вы измените свой гипотетический метод на -objectFromStorage и сделаете так, чтобы он следовал этому шаблону, ваш цикл был бы еще более кратким:

while(someCondition) {
    [container add:[someObject objectFromStorage]];
}
...