Interface Builder中的Singleton与ARC

Iev*_*gen 6 macos singleton objective-c interface-builder automatic-ref-counting

我的问题与此非常相似:在Interface Builder中使用Singleton?

唯一的区别是我使用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
Run Code Online (Sandbox Code Playgroud)

所以问题是,是否可以采用它来使Interface Builder仍然使用ARC?

当然,我明白在没有ARC的情况下重写那个类可能更简单,所以问题是相当学术性的.:)

Dav*_*ong 10

当nib被取消归档时,它将尝试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;
}
Run Code Online (Sandbox Code Playgroud)

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

  • 我的Xcode抱怨说我不能在init方法之外分配self.我通过将`actualInit`重命名为` - (id)initWithNil:(id)theNil`来解决这个问题.工作得非常好. (3认同)