iOS 中的单例对象

Singleton Object in iOS

众所周知,单例对象只能实例化一次,我们在 objective C 中使用单例来全局访问共享资源。我们也知道单例是使用下面的方法来实例化的

    + (instancetype)sharedManager
{
    static PhotoManager *sharedPhotoManager = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        sharedPhotoManager = [[[self class] alloc] init];
        sharedPhotoManager->_photosArray = [NSMutableArray array];
    });
    return sharedPhotoManager;
}

但我也可以这样做 -

PhotoManager *sharedManager = [[PhotoManager alloc] init];

现在这样我还可以创建同一个单例的另一个实例 class 那么如果 class 有两个实例,它怎么会是单例呢?

请说明。

仅当您使用 sharedManager: class 方法时,对象才有单例行为。实例化对象的所有其他方式都不能保证生成单例对象。

当你写

PhotoManager *sharedManager = [[PhotoManager alloc] init];

你没有得到你的 sharedInstance,你正在创建一个新的。你应该使用它的方式是

[PhotoManager sharedInstance];

而不是

PhotoManager *sharedManager = [[PhotoManager alloc] init];

当你创建一个单例时class你从来没有使用过alloc init,你总是应该使用sharedInstance方法在你的应用程序中保持相同的实例

顺便说一下...正如 T_77 建议的那样,您应该使用 dispatch_once 而不是您的实现来创建实例。

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

Objective-C 允许您做很多可能不是预期的事情。如果您知道方法名称,就像调用私有方法一样。

如果您痴迷于确保您的 class 仅用作单例,也许这样的东西会有用:

static PhotoManager *sharedPhotoManager = nil;

+ (instancetype)sharedManager
{
    if (!sharedPhotoManager) {
        sharedPhotoManager = [[PhotoManager alloc] init];
    }
    return sharedPhotoManager;
}

- (instancetype)init {
    if (sharedPhotoManager) {
        // init method is allowed to return different object
        return sharedPhotoManager;
    }
    self = [super init];
    if (self) {

    }
    return self;
}

你可以用这样的技巧来禁止调用 init: 将 - (instancetype)init NS_UNAVAILABLE; 定义添加到您的单例接口。

而不是 [[PhotoManager alloc] init]; 使用 [[[self class] alloc] init];

PhotoManager *sharedManager = [[PhotoManager alloc] init]; 无法编译。

有我的例子:

@interface SomeSingleton : NSObject

+ (instancetype)sharedInstance;
- (instancetype)init NS_UNAVAILABLE;

@end

@implementation SomeSingleton

+ (instancetype)sharedInstance {
    static dispatch_once_t onceToken;
    static SomeSingleton *instance;
    dispatch_once(&onceToken, ^{
        instance = [[[self class] alloc] init];
    });

    return instance;
}

- (instancetype)init {
    self = [super init];

    return self;
}

@end

结果SomeSingleton *s1 = [SomeSingleton sharedInstance];有效,但SomeSingleton *s2 = [[SomeSingleton alloc] init];导致编译错误。