Как заменить слабые ссылки при использовании ARC и таргетинга на iOS 4.0?

87

Я начал разрабатывать свое первое приложение для iOS с Xcode 4.2 и ориентировался на iOS 5.0 с помощью шаблона «служебного приложения» (того, который поставляется с FlipsideViewController).

Я читал, что, поскольку ARC - это функция времени компиляции, она также должна быть совместима с iOS 4, поэтому я попытался настроить свое приложение на 4.3 и попробовать его скомпилировать. Когда я это сделаю, я получаю такую ​​ошибку:

FlipsideViewController.m: ошибка: автоматический подсчет ссылок. Проблема: текущая цель развертывания не поддерживает автоматические __ слабые ссылки.

Ссылка на эту строку:

@synthesize delegate = _delegate;

Эта переменная объявлена ​​как:

@property (weak, nonatomic) IBOutlet id <FlipsideViewControllerDelegate> delegate;

Я понимаю, что «слабые ссылки» не поддерживаются в iOS 4, но я действительно не понимаю, почему я хотел бы использовать слабую ссылку для начала, и я не могу понять, как бы я переписал вещи, чтобы избежать ее использования, в то время все еще пользуется преимуществами ARC (в конце концов, он должен работать с iOS 4 и 5, верно?)

Мейсон Дж. Жвити
источник

Ответы:

149

Чтобы настроить таргетинг на более старую ОС, вы можете использовать unsafe_unretainedвместо этого weakв объявлении свойства, и в основном это должно работать так же. weakссылается на nil, когда их цель исчезает, но unsafe_unretainedоставляет возможность того, что объект, на который вы ссылаетесь, может превратиться в висящий указатель, когда он будет освобожден. Последнее поведение такое же, как если бы вы использовали assignобъявление свойства при ручном управлении памятью.

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

Брэд Ларсон
источник
Спасибо за совет. Вы говорите "нацелить на старую ОС ...". Означает ли это, что я должен использовать unsafe_unrehibited только в сборках приложения старше 5.0? Или я могу просто использовать unsafe_unretended в своем коде и построить его для работы как с 4.x, так и с 5.x?
Мейсон Дж. Жвити, 06
1
@Mason - unsafe_unretainedподдерживается как в iOS 4.x, так и в 5.0, поэтому обеспечивает обратную совместимость. Если вы делали сборку только для 5.0, вы могли бы переключиться на, weakчтобы воспользоваться дополнительной безопасностью, которую она дает.
Брэд Ларсон
Я пробовал unsafe_unrehibited, все равно сработало. Однако я получил много предупреждений вроде '"** __NSAutoreleaseNoPool (): объект 0x564bd90 класса __NSArrayM автоматически выпущен без пула - просто утечка" *', это нормально?
пятый
1
@fifth - это совершенно не связанная с этим проблема. Вы запускаете что-то в фоновом потоке без наличия пула автозапуска. Созданные вручную потоки не имеют собственного пула автозапуска, поэтому вам нужно создать его самостоятельно @autoreleasepool(в ARC, NSAutoreleasePool для более старых реализаций с подсчетом ссылок вручную).
Брэд Ларсон
@Brad, это полезно, предупреждений больше нет, у меня есть несколько вызовов performSelectorInBackground.
пятый
11

Если используются только слабые ссылки для дополнительной безопасности, вручную вызывайте новые функции времени выполнения, если они доступны, и переходите к простому назначению __unsafe_unretainedпеременных, если нет.

ZWRCompatibility.h несколько упростит это.

rpetrich
источник
10

Благодаря библиотеке совместимости PLWeakCompatibilty Майка Эша теперь вы можете просто использовать __weak и в iOS 4.x.

Его невероятно легко настроить, и он не требует дополнительных усилий или усилий по сравнению с 5.x.

ншум
источник