iOS中的单例对象[重复]

Posted

技术标签:

【中文标题】iOS中的单例对象[重复]【英文标题】:Singleton Object in iOS [duplicate] 【发布时间】:2015-08-21 14:22:29 【问题描述】:

我们知道单例对象只能实例化一次,我们在目标 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];

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

请澄清。

【问题讨论】:

【参考方案1】:

您可以使用以下技巧禁止init 的呼叫: 将- (instancetype)init NS_UNAVAILABLE; 定义添加到您的单例界面。

[[[self class] alloc] init];代替[[PhotoManager 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]; 导致编译错误。

【讨论】:

我认为在类方法中你甚至可以省略对class 的调用,因为在类方法中,self 已经引用了类。 @LukasSpieß,你是对的【参考方案2】:

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

【讨论】:

【参考方案3】:

Objective-C 允许你做很多你不打算做的事情。如果您知道方法名称,就像调用私有方法一样。

如果你痴迷于确保你的类只用作单例,也许这样的东西会有用:

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;

【讨论】:

【参考方案4】:

当你写作时

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

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

[PhotoManager sharedInstance];

而不是

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

当您创建一个从未使用过 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;
 

【讨论】:

我还是投了反对票:P @T_77,可能是因为你没有回答这个问题,如果确实可以创建多个对象,为什么它被称为单例。 你是对的。我会记住的。 :) @SonGoku68 请仔细阅读问题。我知道获取共享实例的方法。但我的问题是,如果我们可以分配 init,如何防止创建同一个类的另一个实例。

以上是关于iOS中的单例对象[重复]的主要内容,如果未能解决你的问题,请参考以下文章

实现接口的单例类[重复]

多线程中的单例模式可能具有重复代码

Android 特殊的单例Toast(防止重复显示)

设计模式:Android源码中的单例模式

在多个部署的情况下创建的单例实例的数量 [重复]

C# 中的单例是啥?