16

我已经使用常规模式实现了一个单例对象。我的问题是:是否可以将此对象设置回 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;

仅将本地指针设置sharednil. 毕竟,shared被声明为static.

4

3 回答 3

44

您对本地参考的假设是正确的,它不会影响您的单身人士。

为了能够重新初始化单例,您需要将静态变量移出您的方法,以便整个类都可以访问它。

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了,因为您的单例显然需要多次创建。如果你只从你的 UI 调用这个单例(因此只能从主线程),那么上面的示例就可以了。

如果您需要从多个线程访问,则需要在+sharedInstanceand+resetSharedInstance方法周围加锁,例如

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

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

这比dispatch_once变体要慢很多,但实际上它通常并不重要。

于 2013-06-28T17:03:42.477 回答
5

是的,但是您的单例sharedInstance方法将其定义static为该方法的内部,并且您的最终代码示例只是将局部变量(巧合也称为shared)设置为nil,而static内部sharedInstance保持不变。因此,您只是nil-ing 一个本地指针,而不是更改staticinside sharedInstance

如果你想做你所要求的,你必须把static变量 ,sharedsharedInstance方法中拉出来(并且可能给它写一些reset方法nil)。您的sharedInstance方法也不能再依赖dispatch_once,而是必须检查是否staticnil

于 2013-06-28T17:00:21.560 回答
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;
}
于 2013-12-06T18:53:32.157 回答