在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>,
网友评论