我如何确保Objective-C中的任何时候只有一个类实例?

我如何确保Objective-C中的任何时候只有一个类实例?,objective-c,singleton,retaincount,Objective C,Singleton,Retaincount,这与标准略有不同,因为如果对象的所有外部引用都已释放,那么单例也将被释放。然后,稍后,当请求一个新对象时,将创建一个新的单例。比如说: MyThing *thing1 = [MyThing new]; MyThing *thing2 = [MyThing new]; // thing1 & thing2 are the same object. thing1 = nil; thing2 = nil; thing1 = [MyThing new]; thing2 = [MyThing

这与标准略有不同,因为如果对象的所有外部引用都已释放,那么单例也将被释放。然后,稍后,当请求一个新对象时,将创建一个新的单例。比如说:

MyThing *thing1 = [MyThing new];
MyThing *thing2 = [MyThing new];
// thing1 & thing2 are the same object.

thing1 = nil;
thing2 = nil;

thing1 = [MyThing new];
thing2 = [MyThing new];
// thing1 and thing2 are a the same objet, but it's a different object than above.

我试图使用一个弱静态变量来挂起我的作用域单例,但这不起作用,因为我无法在ARC下增加retain计数。这让我想知道:这可能吗?

覆盖allocWithZone:以管理单个静态实例。如果为nil,则生成一个新版本,如果不是nil,则返回该版本的保留版本

实现dealloc,并在调用nil时调用单个静态实例

我不确定这是否会在ARC中工作,您可能需要为该文件禁用ARC


把这个东西放在周围要花多少钱?遵循标准的单例模式并忘掉它当然不那么麻烦。

根据@KirkSpaziani的回答,我得出以下结论:

static __weak MyTHing *currentThing = nil;

+ (instancetype)allocWithZone:(struct _NSZone *)zone {
    __block id thing = nil;
    dispatch_sync(dispatch_get_global_queue( DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        if (currentThing == nil) {
            currentThing = thing = [super allocWithZone:zone];
        } else {
            thing = currentThing;
        }
    });
    return thing;
}

- (void)dealloc {
    dispatch_sync(dispatch_get_global_queue( DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        currentThing = nil;
    });
}

这假设初始值设定项可以处理“脏数据”,正如。

为什么需要这样做?似乎通过工厂访问的弱引用可以做到这一点。工厂必须像一个单件工厂一样工作。因为我不经常需要这个对象,但当我需要时,我会希望同时在一堆解耦的地方访问同一个对象。thing1和thing2不是同一个对象。它们是类神话的两个不同实例。@HotLicks我是这么想的,但它实际上不起作用。也许我不应该在
-dealoc
中为它赋值
nil
?如果它很弱,当最终引用被释放时,它是否会自动转到
nil
?您还需要旋转
init
,这样如果您已经获得了现有对象,它就不会重新初始化。是的,这似乎是正确的答案。我在
-init
中执行它,但将它移动到
+allocWithZone:
,现在它按预期工作。现在只需找出如何让
-init
对现有对象不做任何操作……我想我已经得到了它,尽管它不是可归纳的(检查是否在
-init
中设置了ivar)。测试通过,但在释放对象之后,在创建新对象之前,我必须调用
NSLog()
,否则我将返回一个具有相同地址的对象。即使使用
NSLog()
我有时也会得到相同地址的对象。现在,只要我能阻止Objective-C在对象被释放后使用相同的内存地址,我就可以进行一次很好的测试,以确保它工作正常。事实上,我可以通过添加
NSLog()
调用日志看到它的工作原理,但我更喜欢可靠的单元测试?这应该是最可靠的方法。此外,如果多个线程可以创建这些对象,考虑使用GCD的DeXCHYSYNC而不是@同步(自)-它应该更有性能。@ KirkSpaziani好调用,谢谢。是的,我通过将log调用放入
-dealoc
中确认了它的有效性,但我需要的是在单元测试运行时分配不使用相同的内存地址。