Почему делегаты должны быть unsafe_unretained и не слабыми?
Я добавил ARC в приложение, над которым я работаю. К сожалению, это вылетает. Я обнаружил, что автоматический скрипт, который обновляет все приложения до ARC, дает спецификатор __unsafe_unretained для всех идентификаторов типа
Почему это не слабый тип? Я развернул приложение и все его подпроекты на iOS 5, поэтому у меня слабые квалификаторы.
Моя главная проблема - если я объявлю этих делегатов сильными, у меня будет цикл сохранения. Если я этого не сделаю, в следующий раз, когда я позвоню им, они будут зомби. Я проверил, и перед сбоем моего приложения, делегатом является NSZombie.
В чем причина этого сбоя и как его можно предотвратить?
2 ответа
Потребовалось время, но я решил:
Я развернул проекты.xcodeproj на iOS 5, но цели остались при развертывании iOS 4.3. Когда я исправил это (это в "настройках сборки" для каждой цели) - я мог изменить все "__unsafe_unretained" на "__weak", а все "unsafe_unretained" на "слабый".
Чтобы избежать сохранения цикла, эти делегаты должны быть слабыми, и они больше не будут зомби (потому что они слабые и не unsafe_unretained), и приложение больше не будет аварийно завершать работу.
Если я все еще пользуюсь iOS4.3-, и нет квалификатора unsafe_unretained, я должен назначить nil этим делегатам только после того, как они мне больше не нужны.
Квалификаторы __unsafe_unretained и week имеют довольно много общего. Например, они оба не увеличат количество сохраняемых данных. Если, например, контроллер представления хранит IBOutlet __unsafe_unretained в UIView, и вы удаляете этот самый UIView из иерархии представления, то вы (учитывая, что вы нигде не сохраняете представление) уменьшите счет сохранения и, скорее всего, освободите UIView, Однако указатель все равно будет указывать на это место и будет зависать. Не приятно, но и не проблема, если вы знаете, что случилось. Слабые свойства помогают вам избежать висячих указателей, обнуляя свойство, когда объект получает счет 0.
Теперь, если ваше приложение вылетает или свойства отображаются как зомби, они освобождаются - в зависимости от класса.
Одно утверждение, которое не совсем корректно, заключается в том, что если вы сохраните это свойство, вы создадите цикл сохранения. Существует возможность создания циклов сохранения, но это действительно зависит от вашей реализации, а не только от объявления свойства. Когда вы сохраняете объект, вы вступаете во владение и до тех пор, пока не закончите работу с этим объектом, предотвратите его освобождение, увеличив количество сохраняемых объектов. Если ваш делегат уже освобожден, пока вы держите слабый указатель, вы не будете препятствовать его освобождению. Я предполагаю, что вы имеете дело с контроллерами модального представления здесь - UIPopoverController, если быть точным (только предположение).
Вы должны использовать инструменты и посмотреть на жизненный цикл вашего объекта и посмотреть, кто его хранит / выпускает. Это может быть полезно знать. В противном случае, вы можете вставить некоторый код, и, возможно, здесь найдется хороший человек, который поможет вам найти проблему.
ура Ронни