单例是一个类有且只有一个实例,并且自行实例化向整个系统提供
static XSSingletonManager * instance = nil;
@implementation XSSingletonManager
+(instancetype)XSShareInstance{
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
instance = [[self alloc]init];
});
return instance;
}
- 做如下测试:
XSSingletonManager * objc1 = [XSSingletonManager XSShareInstance];
NSLog(@"%@",objc1);
XSSingletonManager * objc2 = [XSSingletonManager new];
NSLog(@"%@",objc2);
XSSingletonManager * objc3 = [[XSSingletonManager alloc]init];
NSLog(@"%@",objc3);
测试结果打印出来
2021-06-10 11:54:25.420181+0800 runLoop[5676:2178711] <XSSingletonManager: 0x2821e4730>
2021-06-10 11:54:25.420274+0800 runLoop[5676:2178711] <XSSingletonManager: 0x2821e4720>
2021-06-10 11:54:25.420356+0800 runLoop[5676:2178711] <XSSingletonManager: 0x2821e4710>
很明显,通过三种方式创建出来的三个实例是不同的,这个就违背单例的原则(有且仅有一个实例)
为了防止别人使用alloc/init的方式创建对象,我们要保证自己的类不管用什么方式创建,只能创建同一个实例对象,需要重写一个方法
+(instancetype)allocWithZone:(struct _NSZone *)zone{
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
instance = [super allocWithZone:zone];
});
return instance;
}
再次调用上面的测试代码,结果如下
2021-06-10 12:52:43.563003+0800 runLoop[5722:2196911] <XSSingletonManager: 0x282978670>
2021-06-10 12:52:43.563049+0800 runLoop[5722:2196911] <XSSingletonManager: 0x282978670>
2021-06-10 12:52:43.563085+0800 runLoop[5722:2196911] <XSSingletonManager: 0x282978670>
再次给单例类里面加几个属性
@property (nonatomic,strong) NSObject * object;
@property (nonatomic,strong) NSMutableArray * array;
@property (nonatomic,assign) NSInteger num;
而一些对象类的初始化,或者是基础类型的默认值设置,都是在init方法里面
-(instancetype)init{
self = [super init];
if (self) {
_num = 10;
_object = [[NSObject alloc]init];
_array = [NSMutableArray array];
}
return self;
}
重写了description
方法
-(NSString *)description{
NSString * result = @"";
result = [result stringByAppendingFormat:@"<%@:%p>",[self class],self];
result = [result stringByAppendingFormat:@" num = %ld",(long)self.num];
result = [result stringByAppendingFormat:@" array = %p",self.array];
result = [result stringByAppendingFormat:@" object = %p",self.object];
return result;
}
调用上面的测试代码
2021-06-10 13:55:46.330450+0800 runLoop[5772:2214526] <XSSingletonManager:0x28199fd60> num = 10 array = 0x2817da4c0 object = 0x281bbc5d0
2021-06-10 13:55:46.330543+0800 runLoop[5772:2214526] <XSSingletonManager:0x28199fd60> num = 10 array = 0x2817da370 object = 0x281bbc5c0
2021-06-10 13:55:46.330615+0800 runLoop[5772:2214526] <XSSingletonManager:0x28199fd60> num = 10 array = 0x2817dac10 object = 0x281bbc5e0
可以看到尽管使用的是同一个实例,可是他的property的值确不一样,因为尽管没有为实例重新分配内存空间,但是又因为执行了init方法,会导致property被重新初始化
所以我们需要修改单例的实现。
第1种方法
将property的初始化或者默认值设置到dispatch_once的block内部
+(instancetype)XSShareInstance{
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
instance = [[self alloc]init];
instance.num = 10;
instance.object = [[NSObject alloc]init];
instance.array = [NSMutableArray array];
});
return instance;
}
-(NSString *)description{
NSString * result = @"";
result = [result stringByAppendingFormat:@"<%@:%p>",[self class],self];
result = [result stringByAppendingFormat:@" num = %ld",(long)self.num];
result = [result stringByAppendingFormat:@" array = %p",self.array];
result = [result stringByAppendingFormat:@" object = %p",self.object];
return result;
}
+(instancetype)allocWithZone:(struct _NSZone *)zone{
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
instance = [super allocWithZone:zone];
});
return instance;
}
测试下看下结果
2021-06-10 15:06:08.246233+0800 runLoop[5790:2237632] 此设备未越狱
2021-06-10 15:06:08.246398+0800 runLoop[5790:2237632] <XSSingletonManager:0x283b7ed20> num = 10 array = 0x28353a370 object = 0x283954620
2021-06-10 15:06:08.246467+0800 runLoop[5790:2237632] <XSSingletonManager:0x283b7ed20> num = 10 array = 0x28353a370 object = 0x283954620
2021-06-10 15:06:08.246533+0800 runLoop[5790:2237632] <XSSingletonManager:0x283b7ed20> num = 10 array = 0x28353a370 object = 0x283954620
第2种
+(instancetype)XSShareInstance{
return [[self alloc] init];
}
-(instancetype)init{
if (self = [super init]) {
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
instance = [super init];
instance.num = 10;
instance.object = [[NSObject alloc]init];
instance.array = [NSMutableArray array];
});
return instance;
}
return self;
}
-(NSString *)description{
NSString * result = @"";
result = [result stringByAppendingFormat:@"<%@:%p>",[self class],self];
result = [result stringByAppendingFormat:@" num = %ld",(long)self.num];
result = [result stringByAppendingFormat:@" array = %p",self.array];
result = [result stringByAppendingFormat:@" object = %p",self.object];
return result;
}
+(instancetype)allocWithZone:(struct _NSZone *)zone{
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
instance = [super allocWithZone:zone];
});
return instance;
}
测试下看下结果:
2021-06-10 15:11:30.544370+0800 runLoop[5797:2239565] <XSSingletonManager:0x283b7f900> num = 10 array = 0x283535ad0 object = 0x283958940
2021-06-10 15:11:30.544449+0800 runLoop[5797:2239565] <XSSingletonManager:0x283b7f900> num = 10 array = 0x283535ad0 object = 0x283958940
2021-06-10 15:11:30.544504+0800 runLoop[5797:2239565] <XSSingletonManager:0x283b7f900> num = 10 array = 0x283535ad0 object = 0x283958940
网友评论