Interface Builder中的Singleton与ARC

时间:2012-11-21 22:28:49

标签: objective-c macos interface-builder singleton automatic-ref-counting

我的问题与此问题非常相似:Use Singleton In Interface Builder?

唯一的区别是我使用ARC。所以,如果简化,我的单身人员就是这样:

Manager.m

@implementation Manager

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

@end

所以问题是,是否可以将它用于仍然使用ARC的Interface Builder?

当然,我理解在不使用ARC的情况下重写该类可能更简单,因此问题相当于学术性。 :)

3 个答案:

答案 0 :(得分:10)

取消存档笔尖后,它会尝试alloc / initalloc / initWithCoder:新的类实例。

所以,你可以做的是拦截那个召唤并重新路由它以返回你的单身人士:

+ (id)sharedInstance {
  static Singleton *sharedInstance = nil;
  static dispatch_once_t onceToken;
  dispatch_once(&onceToken, ^{
    sharedInstance = [[self actualAlloc] actualInit];
  });
  return sharedInstance;
}

+ (id)actualAlloc {
  return [super alloc];
}

+ (id)alloc {
  return [Singleton sharedInstance];
}

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

- (id)init {
  return self;
}

- (id)initWithCoder:(NSCoder *)decoder {
  return self;
}

这允许在同一对象上多次安全地调用-init-initWithCoder:。一般不建议允许这样做,但鉴于单身人士已经成为“事情变得非常糟糕的地方”,这不是你能做的最糟糕的事情。

答案 1 :(得分:3)

为了完成,这里是Singleton的一个实现,可以在Interface Builder中使用。区别在于actualAlloc方法。由于[super alloc]仍然会调用[self allocWithZone:] - 它不会分配对象。

Singleton.h

@interface Singleton : NSObject

+ (instancetype)sharedInstance;

@end

Singleton.m

@implementation Singleton

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

+ (id)allocWithZone:(NSZone *)zone {
    return [self sharedInstance];
}

+ (id)alloc {
    return [self sharedInstance];
}

- (id)init {
    return self;
}

+ (id)_alloc {
    return [super allocWithZone:NULL]; //this is important, because otherwise the object wouldn't be allocated
}

- (id)_init {
    return [super init];
}

@end

答案 2 :(得分:0)

来自iOS文档集的@Eugene,“由于历史原因,alloc调用allocWithZone:。”,因此,无需重新实现alloc方法。