【问题标题】:Creating a singleton and overriding the alloc class method创建单例并覆盖 alloc 类方法
【发布时间】:2014-08-27 09:43:52
【问题描述】:

我使用以下代码创建了一个单例类:

static MyClass *sharedMyClass = nil;

+ (id)getInstance {
  static dispatch_once_t onceToken;
  dispatch_once(&onceToken, ^{
    sharedMyClass = [[self alloc] init];
  });
  return sharedMyClass;
}

我担心我的类的用户可以调用 alloc 方法来创建该类的其他实例。因此,这将不再是单例我需要重写 alloc 方法吗?如果是这样,我建议以这种方式覆盖它:

+ (id)alloc
{
  id instance = sharedMyClass;
  if (instance == nil) {
    instance = [super alloc];
  }
  return instance;
}

【问题讨论】:

  • +(id)alloc { @synchronized([MyClass class]) { NSAssert(_sharedNavTheme == nil, @"试图分配第二个单例实例。"); _sharedMyClass = [超级分配];返回_sharedMyClass; } 返回零; }

标签: ios objective-c singleton instantiation alloc


【解决方案1】:

这样实现?

+(id)alloc
{ @synchronized([MyClass class])
    {
        NSAssert(_sharedMyClass == nil, @"Attempted to allocate a second instance of a singleton.");
        _sharedMyClass = [super alloc];
        return _sharedMyClass;
    }
    return nil;
}

【讨论】:

  • _sharedNavTheme 是什么意思?
  • 为什么它在@synvhronized 指令下?有什么东西使它线程不安全吗?
  • _sharedNavTheme 是我的单身我忘了编辑它我现在更正了:) 和@synchronized 使它线程安全而不是不安全。它确保不超过一个线程可以使用它绑定的代码:)
【解决方案2】:

是的,您需要覆盖 alloc 方法。

您可以通过实施来归档它

+ (instancetype)sharedInstance {
    static MyClass *sharedInstance = nil;

    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        sharedInstance = [[super allocWithZone:NULL] init];
    });

    return sharedInstance;
}

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

- (id)copyWithZone:(NSZone *)zone {
    return self;
}

Apple 提供了此案例的详细说明,您可以在此处找到(非 ARC 说明)https://developer.apple.com/legacy/library/documentation/Cocoa/Conceptual/CocoaFundamentals/CocoaObjects/CocoaObjects.html#//apple_ref/doc/uid/TP40002974-CH4-SW32

【讨论】:

    【解决方案3】:

    你可以在编译时禁止alloc

    + (instancetype)new NS_UNAVAILABLE;
    + (instancetype)alloc NS_UNAVAILABLE;
    

    在您自己的实现中使用super alloc

    + (instancetype)getInstance {
      static id sharedMyClass
      static dispatch_once_t onceToken;
      dispatch_once(&onceToken, ^{
        sharedMyClass = [[super alloc] init];
      });
      return sharedMyClass;
    }
    

    它并不能保护您免受一些运行时代码的影响,但它已经足够清晰了。

    【讨论】:

      猜你喜欢
      • 2011-11-12
      • 1970-01-01
      • 1970-01-01
      • 2011-02-25
      • 1970-01-01
      • 1970-01-01
      • 2023-02-09
      • 2010-09-06
      • 2012-07-19
      相关资源
      最近更新 更多