单例的正确使用

2018-03-30  本文已影响12人  MeteorCode

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

需要注意两点:

单例中的实例地址发生了变化?
+ (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>,
上一篇下一篇

猜你喜欢

热点阅读