【问题标题】:Upgrade an existing singleton to ARC将现有单例升级到 ARC
【发布时间】:2012-12-07 02:44:59
【问题描述】:

在 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方法是否安全?谢谢!

【问题讨论】:

  • 如果 wevah 的回答对您有帮助,您应该将其标记为正确答案,以便对其他人有所帮助。仅供参考。

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


【解决方案1】:

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

+ (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,从而可以立即识别发生了什么。)

【讨论】:

  • strong static id _sharedInstance = nil; 有什么意义吗?我在一些旧代码中有这个,我认为它可能是为了抑制警告,但我不确定。这有什么不同吗?更好,更坏,还是草率?
  • 所有引用默认为strong。所以,不,没有意义。而且,真的,也不需要初始化为nil(因为这是自动的)。
【解决方案2】:

是的。

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

【讨论】:

  • @Wevah 我真的很想知道答案,仅删除保留、保留计数、释放、自动释放方法是否安全?谢谢!
  • 可以,只要你只通过类方法访问单例(例如,+sharedObject)。
猜你喜欢
  • 1970-01-01
  • 2015-06-15
  • 2011-03-18
  • 1970-01-01
  • 1970-01-01
  • 2021-06-03
  • 1970-01-01
  • 2019-05-29
  • 2012-06-08
相关资源
最近更新 更多