将现有单例升级为ARC

时间:2012-12-07 02:44:59

标签: objective-c singleton automatic-ref-counting

在Objective-C中,如何用ARC编写单例?在ARC中,不允许覆盖release,autorelease,retain,retainCount方法,如何避免释放对象?我知道没有ARC,下面会有一个经典的单身人士:

@interface SingletonObject
+ (SingletonObject*)sharedObject;
@end

SingletonObject *sharedObj;

@implementation SingletonObject
+ (id)allocWithZone:(NSZone *)zone
{
    if (sharedObj == nil) {
        //So the code [[SingletonObject alloc] init] is equal with [SingletonObject sharedObject]
        sharedObj = [super allocWithZone:zone];
    }
    return sharedObj; 
}


+ (void)initialize
{
    if (self == [SingletonObject class]) {
        sharedObj = [[SingletonObject alloc] init];
    }
}

+ (SingletonObject*)sharedObject
{
    return sharedObj;
}
- (id)retain
{
    return self;
}

- (unsigned)retainCount
{
    return UINT_MAX;  //denotes an object that cannot be released
}

- (oneway void)release
{
    //do nothing
}

- (id)autorelease
{
    return self;
}

- (id)init {
    self  = [super init];
    if (self) {
       //... 
    }
    return self;
}

@end

删除retain,retainCount,release,autorelease方法是否安全?谢谢!

2 个答案:

答案 0 :(得分:8)

您只需要一种方法来实现支持单例模式的类:

+ (instancetype)sharedInstance
{
    static id _sharedInstance = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        _sharedInstance = [[self alloc] init];
    });
    return _sharedInstance;
}

将其复制/粘贴到任何类中,它将具有共享实例。除此之外的任何代码只是增加了实际上不必要的复杂性。我有时会添加:

- (void)dealloc
{
     *(char*)0x42 = 'b';
     // no super, ARC all the way
}

如果我的共享实例由于错误而被解除分配,那将导致非常具体的崩溃。 (是的,十六进制0x42不是42,但它在崩溃日志中的寄存器中留下了一个很好的0x000000042,使其立即可识别发生了什么。)

答案 1 :(得分:0)

-sharedObject应该是+sharedObject,但是(类方法)。只要确保你总是使用它。