6

私の質問はこれと非常に似ています: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にあるInterfaceBuilderに採用することが可能かどうかということです。

もちろん、ARCなしでそのクラスを書き直す方が簡単かもしれないことを理解しているので、質問はかなり学術的です。:)

4

3 に答える 3

9

allocnib がアーカイブ解除されると、 /initまたはalloc/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:同じオブジェクトに対して安全に複数回呼び出すことができます。通常、これを許可することはお勧めしませんが、シングルトンがすでに「物事が本当に不安定になる可能性がある場所」のケースであることを考えると、これはあなたができる最悪のことではありません。

于 2012-11-21T23:02:21.423 に答える
2

完成させるために、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
于 2012-11-27T19:21:56.737 に答える
0

iOS doc セットの @Eugene は、「歴史的な理由から、 . をalloc呼び出す」ため、メソッドallocWithZone:を再実装する必要はありません。alloc

于 2013-05-11T05:32:54.323 に答える