美文网首页ios tips
iOS中的单例你用对了么?

iOS中的单例你用对了么?

作者: Gyuanhang | 来源:发表于2017-12-11 23:10 被阅读0次

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

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

    最近看到一些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的时候,初始化的属性会覆盖之前的属性

    相关文章

      网友评论

        本文标题:iOS中的单例你用对了么?

        本文链接:https://www.haomeiwen.com/subject/feawixtx.html