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];
导致编译错误。
众所周知,单例对象只能实例化一次,我们在 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];
导致编译错误。