Подтвердить что ты не робот

Можно ли установить singleton обратно в nil?

Я реализовал одноэлементный объект, используя обычный шаблон. Мой вопрос: возможно ли вернуть этот объект в нуль, так что на более поздней странице [MySingleton sharedInstance] объект будет повторно инициализирован?

// Get the shared instance and create it if necessary.
+ (MySingleton *)sharedInstance {

    static dispatch_once_t pred;
    static MySingleton *shared = nil;
    dispatch_once(&pred, ^{
        shared = [[MySingleton alloc] init];
    });
    return shared;
}

// We can still have a regular init method, that will get called the first time the     Singleton is used.
- (id)init 
{
    self = [super init];

    if (self) {
    // Work your initialising magic here as you normally would

    }
    return self;
}

Я предполагаю, что

MySingleton *shared = [MySingleton sharedInstance];
shared = nil;

устанавливает только локальный указатель shared в nil. В конце концов, shared объявляется как static.

4b9b3361

Ответ 1

Ваше предположение о локальной ссылке правильное, это не повлияет на ваш синглтон.

Чтобы иметь возможность повторно инициализировать синглтон, вам нужно переместить статическую переменную из вашего метода, чтобы она была доступна для всего класса.

static MySingleton *sharedInstance = nil;
// Get the shared instance and create it if necessary.
+ (MySingleton *)sharedInstance {
    if (sharedInstance == nil) {
        sharedInstance = [[MySingleton alloc] init];
    }
    return sharedInstance;
}

+ (void)resetSharedInstance {
    sharedInstance = nil;
}

Обратите внимание, что вы больше не можете использовать dispatch_once, так как ваш singleton должен быть создан несколько раз. Если вы только когда-либо называете этот синглтон из своего пользовательского интерфейса (и, следовательно, только из основного потока), то пример выше в порядке.

Если вам нужен доступ из нескольких потоков, вам нужно поместить блокировку вокруг методов +sharedInstance и +resetSharedInstance, например.

+ (id)sharedInstance {
    @synchronized(self) {
        if (sharedInstance == nil) {
            sharedInstance = [[MySingleton alloc] init];
        }
        return sharedInstance;
    }
}

+ (void)resetSharedInstance {
    @synchronized(self) {
        sharedInstance = nil;
    }
}

Это немного медленнее, чем вариант dispatch_once, но на практике это не имеет значения.

Ответ 2

Да, но ваш метод singleton sharedInstance определяет его как static внутри этого метода, а ваш окончательный образец кода просто устанавливает локальную переменную (по совпадению, также называемую shared) на nil, оставляя static внутри sharedInstance без изменений. Таким образом, вы просто nil, указав локальный указатель, не меняя static внутри sharedInstance.

Если вы хотите выполнить то, что вы просите, вам придется вытащить переменную static, shared, из метода sharedInstance (и предположительно написать некоторый метод reset для nil Это). Ваш метод sharedInstance также больше не может полагаться на dispatch_once, но должен проверить, не является ли это static nil или нет.

Ответ 3

Я сделал это. Я не уверен, что это лучший способ, но, похоже, он работает нормально.

static dispatch_once_t pred;
static MySingleton *shared = nil;

+(MySingleton *)sharedInstance {
        dispatch_once(&pred, ^{
            shared = [[MySingleton alloc] init];
        });
        return shared;
    }

+(void)clearSharedInstance {

       shared = nil;
       pred = nil;
}