Как освободить объект экземпляра, созданный с помощью dispatch_once

Я использую ARC для своего проекта

У меня есть 1 класс:

@implementation MyObject

+ (instancetype)shareInstance {
    static id _shareInstance = nil;
    static dispatch_once_t oncePredicate;
    dispatch_once(&oncePredicate, ^{
        _shareInstance = [[self alloc] init];
        [[NSNotificationCenter defaultCenter] addObserver:self
                                                 selector:@selector(freeInstance)
                                                     name:kLC_Notification_FreeAllInstance object:nil];
    });
    return _shareInstance;
}
+ (void)freeInstance {
    /*I want to release object "_shareInstance" but how??? */
    [[NSNotificationCenter defaultCenter] removeObserver:self];
}
@end

Но я не могу освободить свой объект экземпляра, поэтому мне нужно изменить:

(переместить строку кода static id _shareInstance = nil; из +shareInstance

@implementation MyObject
static id _shareInstance = nil;
+ (instancetype)shareInstance {
    static dispatch_once_t oncePredicate;
    dispatch_once(&oncePredicate, ^{
        _shareInstance = [[self alloc] init];
        [[NSNotificationCenter defaultCenter] addObserver:self
                                                 selector:@selector(freeInstance)
                                                     name:kLC_Notification_FreeAllInstance object:nil];
    });
    return _shareInstance;
}
+ (void)freeInstance {
    _shareInstance = nil;
    [[NSNotificationCenter defaultCenter] removeObserver:self];
}
@end

Когда я нажимаю уведомление с именем: kLC_Notification_FreeAllInstance, все объекты экземпляра освобождаются (вызываются все методы Dealloc). Все в порядке

НО когда я позвоню ему снова....

все экземпляры не инициализируются при следующем вызове. И после этого все объекты экземпляров будут равны нулю

Я сделал много точек останова в блоке dispatch_once, и ни одна точка останова не вызывается.


Итак, мои вопросы:

  1. Написание static id object; в методе и запись вне метода — это разные вещи?

  2. Как я могу освободить все объекты экземпляра, чтобы я мог снова вызывать их? (Я хочу использовать ARC, я могу сделать это без ARC)


person Tony    schedule 09.10.2013    source источник


Ответы (2)


Чтобы ответить на ваш вопрос по порядку...

  1. Разница между записью статической переменной внутри и снаружи метода заключается в области видимости, т. е. при записи статической переменной внутри метода она доступна только внутри этого метода.

  2. Это немного сложнее, как следует из имени dispatch_once, который запускает код в блоке только один раз, но я считаю, что он полагается на токен/предикат для синхронизации, поэтому перемещение этого за пределы shareInstance и установка на 0 должны означать, что dispatch_once запускает блок (один раз) в следующий раз

person Nick Banks    schedule 09.10.2013

Я думаю, что вы должны установить oncePredicate на 0 при выпуске _shareInstance

@implementation MyObject
static id _shareInstance = nil;
static dispatch_once_t oncePredicate;
+ (instancetype)shareInstance {
    dispatch_once(&oncePredicate, ^{
        _shareInstance = [[self alloc] init];
        [[NSNotificationCenter defaultCenter] addObserver:self
                                                 selector:@selector(freeInstance)
                                                     name:kLC_Notification_FreeAllInstance object:nil];
    });
    return _shareInstance;
}
+ (void)freeInstance {
    _shareInstance = nil;
    oncePredicate = 0;
    [[NSNotificationCenter defaultCenter] removeObserver:self];
}
@end

Меня устраивает!

person Tuan Do    schedule 11.03.2014
comment
О, да! Спасибо. Это работает и для меня. Я думаю, что dispatch_once основывается на oncePredicate var для вызова своего блока. - person Tony; 11.03.2014