iOS中的单例你用对了么?

单例模式怎么定义的,可能在不同的语言,不同的书中不完全一样,但是概况开来都应该是:一个类有且仅有一个实例,并且自行实例化向整个系统提供。

因此,首先你可能需要确定你是真的需要一个单例类,还是说仅仅是需要一个方便调用的实例化方法。如果你是真的需要一个单例类,那么你就应该确保这个单例类,有且仅有一个实例(不管怎么操作都只能获取到这个实例)。

最近看到一些github上的单例使用,别人的用法,有一些思考,然后写demo测试了下,就这个简单的单例也有一些坑呢,希望能给他人一些提醒。

我们通常在OC中实现一个单例方法都是这样

static HLTestObject *instance = nil;

+ (instancetype)sharedInstance

{

static dispatch_once_t onceToken;

dispatch_once(&onceToken, ^{

instance = [[[self class] alloc] init];

});

return instance;

}

可是这样就可以了么?我做了如下测试:HLTestObject *objct1 = [HLTestObject sharedInstance];

NSLog(@"%@",objct1);

HLTestObject *objc2 = [[HLTestObject alloc] init];

NSLog(@"%@",objc2);

HLTestObject *objc3 = [HLTestObject new];

NSLog(@"%@",objc3);


看到这个测试,你想到打印结果了么?结果是这样的:

2016-05-23 12:52:57.095 PractiseProject[3579:81998]2016-05-23 12:52:57.095 PractiseProject[3579:81998]2016-05-23 12:52:57.095 PractiseProject[3579:81998]

很明显,通过三种方式创建出来的是不同的实例对象,这就违背了单例类有且仅有一个实例的定义。

为了防止别人不小心利用alloc/init方式创建示例,也为了防止别人故意为之,我们要保证不管用什么方式创建都只能是同一个实例对象,这就得重写另一个方法,实现如下:

+ (instancetype)allocWithZone:(struct _NSZone *)zone

{

static dispatch_once_t onceToken;

dispatch_once(&onceToken, ^{

instance = [super allocWithZone:zone];

});

return instance;

}

再次用上面的测试代码,结果是这样的

2016-05-23 12:57:37.396 PractiseProject[3618:83975]2016-05-23 12:57:37.396 PractiseProject[3618:83975]2016-05-23 12:57:37.396 PractiseProject[3618:83975]

注意如果单例有属性的话,不要重写init方法, 在

+ (instancetype) sharedInstance

方法中初始化,即可,不然,调用init的时候,初始化的属性会覆盖之前的属性

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 在开发中经常会用到单例设计模式,目的就是为了在程序的整个生命周期内,只会创建一个类的实例对象,而且只要程序不被杀死...
    不要重名就好阅读 560评论 0 0
  • 在开发中经常会用到单例设计模式,目的就是为了在程序的整个生命周期内,只会创建一个类的实例对象,而且只要程序不被杀死...
    VincentHK阅读 688评论 0 3
  • 单例:意思就是只有一个实例。单例模式确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例。这个类称为单...
    CoderZS阅读 617评论 1 13
  • 在开发中经常会用到单例设计模式,目的就是为了在程序的整个生命周期内,只会创建一个类的实例对象,而且只要程序不被杀死...
    零度_不结冰阅读 449评论 0 0
  • 问题 最近排查一个crash 问题,读了一下crash Log以后,发现堆栈报的错误信息非常奇怪。相似在对一个单例...
    还是那个西海阅读 10,127评论 0 9