美文网首页
单例的正确使用

单例的正确使用

作者: MeteorCode | 来源:发表于2018-03-30 16:29 被阅读12次

    在iOS开发中,如何争取地使用单例呢?
    单例:就是一个类有且只要一个实例,这个实例供整个系统使用。也就是这个实例对象一旦被创建,所分配的内存地址是不会发生变化了。

    需要注意两点:

    • 如果不小心用了aolloc/init或者new创建,这个实例的地址发生变化了么?
    • 如果不小心用了aolloc/init或者new创建,里面属性所分配的内存空间发生变化了么?
    单例中的实例地址发生了变化?
    + (instancetype)sharedSession {
        
        static TDSession *session = nil;
        static dispatch_once_t onceToken;
        dispatch_once(&onceToken, ^{
            session = [[TDSession alloc] init];
        });
        return session;
    }
    

    使用不同的方式创建这个实例:

        TDSession *session = [TDSession sharedSession];  //单例方式
        NSLog(@"0-- %@",session);
    
        TDSession *session1 = [TDSession new];//直接new
        NSLog(@"1-- %@",session1);
    
        TDSession *session2 = [[TDSession alloc] init];//alloc分配
        NSLog(@"2-- %@",session2);
    

    打印的结果:

    EdxProject[459:58489] 0-- <TDSession: 0x170030fe0>
    EdxProject[459:58489] 1-- <TDSession: 0x17403afa0>
    EdxProject[459:58489] 2-- <TDSession: 0x17403af60>
    

    打印出来的是三个不同的实例,违背了单例的使用定义;
    解决的方法是:重写类中的allocWithZone:方法

    static TDSession *session = nil;
    
    + (instancetype)sharedSession {
        static dispatch_once_t onceToken;
        dispatch_once(&onceToken, ^{
            session = [[TDSession alloc] init];
        });
        return session;
    }
    
    + (instancetype)allocWithZone:(struct _NSZone *)zone {
        static dispatch_once_t onceToken;
        dispatch_once(&onceToken, ^{
            session = [super allocWithZone:zone];
        });
        return session;
    }
    

    使用不同的方式创建打印出来的结果是:

    EdxProject[464:59656] 0-- <TDSession: 0x17003f900>
    EdxProject[464:59656] 1-- <TDSession: 0x17003f900>
    EdxProject[464:59656] 2-- <TDSession: 0x17003f900>
    
    实例中的属性分配的内存空间发生了变化?
    + (instancetype)sharedSession {
        static dispatch_once_t onceToken;
        dispatch_once(&onceToken, ^{
            session = [[TDSession alloc] init];
        });
        return session;
    }
    
    - (instancetype)init {
        if (self = [super init]) {
            self.store = [[TDStorage alloc] init];
        }
        return self;
    }
    

    然后在类中重写 description方法,来打印用不用方法创建实例,其中的属性分配的内存空间是否发生变化;注意,description方法实在nslog时候才会调用:

    - (NSString *)description {
        NSString *result = @"";
        result = [result stringByAppendingFormat:@"%@--->>  %p>",[self class], self];
        result = [result stringByAppendingFormat:@"--->>> %@,",self.credentialStore];
        return result;
    }
    

    使用不同的方式创建打印出来的结果是:

    EdxProject[471:60584] 0-- TDSession--->>  0x174032560>--->>> < TDStorage: 0x1740017e0>,
    EdxProject[471:60584] 1-- TDSession--->>  0x174032560>--->>> < TDStorage: 0x170009610>,
    EdxProject[471:60584] 2-- TDSession--->>  0x174032560>--->>> < TDStorage: 0x170009650>,
    

    解决的方法是:将属性对象的创建,赋值放到单例中,不要放在init方法里面;

    + (instancetype)sharedSession {
    
        static dispatch_once_t onceToken;
        dispatch_once(&onceToken, ^{
            session = [[TDSession alloc] init];
            session.store = [[TDStorage alloc] init];
        });
        return session;
    }
    
    - (instancetype)init {
        if (self = [super init]) {
        }
        return self;
    }
    

    打印出来的接口:

    EdxProject[475:61533] 0-- TDSession--->>  0x170236420>--->>> < TDStorage: 0x1700104e0>,
    EdxProject[475:61533] 1-- TDSession--->>  0x170236420>--->>> < TDStorage: 0x1700104e0>,
    EdxProject[475:61533] 2-- TDSession--->>  0x170236420>--->>> < TDStorage: 0x1700104e0>,
    

    相关文章

      网友评论

          本文标题:单例的正确使用

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