Кластер классов с ARC
Я пытаюсь создать кластер классов в качестве подкласса UIViewController
для достижения некоторых пунктов:
1. Различное поведение ViewController в зависимости от актуальной версии iOS
2. Проверки версии iOS не загромождают код
3. Абоненту не нужно заботиться
Пока я получил классы MyViewController
, MyViewController_iOS7
а также MyViewController_Legacy
,
Для создания экземпляров я вызываю метод myViewControllerWithStuff:(StuffClass*)stuff
который реализован как:
+(id)myViewControllerWithStuff:(StuffClass*)stuff
{
if (NSFoundationVersionNumber > NSFoundationVersionNumber_iOS_6_1)
{
return [[MyViewController_iOS7 alloc] initWithStuff:stuff];
}
else
{
return [[MyViewController_Legacy alloc] initWithStuff:stuff];
}
}
Вызывающая сторона использует myViewControllerWithStuff:
, После этого созданный таким образом контроллер представления выдвигается на UINavigationController
Навигационный стек.
Это почти работает, как и предполагалось, с одним большим недостатком: ARC не освобождает экземпляр MyViewController_xxx
когда он выскочил из стека навигации. Не имеет значения, какая версия iOS.
Что мне не хватает?
ОБНОВЛЕНИЕ: -initWithStuff:
-(id)initWithStuff:(StuffClass*)stuff
{
if (self = [super init])
{
self.stuff = stuff;
}
return self;
}
Этот метод также реализован в MyViewController
, Различия всплывают позже (например, viewDidLoad:
).
1 ответ
Прежде всего: спасибо за вашу помощь, комментарии, ответы, предложения...
Конечно был другой strong
ссылка на MyViewController
-объект. Но это было не так очевидно, потому что это не было свойством или переменной экземпляра.
В viewDidLoad
Я сделал следующее:
[[NSNotificationCenter defaultCenter] addObserverForName:UIApplicationWillResignActiveNotification object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *note) {
[self saveState];
}];
Это должно предотвратить потерю данных в случае, если пользователь отправляет приложение в фоновый режим. Конечно, блок захватывает необходимые части своего окружения. В этом случае он захватил self
, Блок держит self
жив, пока он (блок) не будет уничтожен, как, например, [[NSNotificationCenter defaultCenter] removeObserver:self];
вызывается. Но, не повезло, этот звонок помещен в dealloc
метод MyViewController
который не будет вызван, пока существует блок...
Исправление заключается в следующем:
__weak MyViewController *weakSelf = self;
[[NSNotificationCenter defaultCenter] addObserverForName:UIApplicationWillResignActiveNotification object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *note) {
[weakSelf saveState];
}];
Теперь блок захватывает weakSelf
, Таким образом, он не может держать MyViewController
-объект живой и все освобождает и работает просто отлично.