前言
什么是单例?
一个类只有一个实例(一个对象),而且该实例易于供外界访问,从而方便地控制了实例个数,并节约系统资源
正题
在iOS开发中单例是很平常的模式,但是昨天去面试的时候被人问到了一个比较尴尬的问题。
平常在项目中我们书写的单例大概应该都是这个样子,现在.h
文件中声明一个类方法
@implementation Singleton
+(instancetype)shareInstance;
@end
然后在.m
中去实现这个方法
@implementation Singleton
static Singleton *instance = nil;
+(instancetype)shareInstance{
static dispatch_once_t onceToken;
dispath_once(&onceToken,^{
instance = [[self alloc]init];
});
return instance;
}
但是,昨天有人问了这么一个问题,说一般的都知道这个类方法是创建单例的,假如我不知道,我直接走了[[self alloc]init]
方法来创建这个对象。那是不是就不能保证这个对象类的唯一性了?
仔细想一下好像是这样,这也是我个人的问题。在写项目的时候没有注意到这么个问题。在当时那个是时候我是被难住了......
之后我就写了一个demo试了一下
这时我们再看看控制台中打印出来的信息single1
和single2
的地址是一样的,因为都是走了那个类方法,可是single3
就不一样了,这个时候这个Singleton
就不严谨了。
解决问题
之后我就去网上找了一下,网上真的有很多人已经写过这样的技术博客了。我就去试了试。
主要就是为了确保对象的唯一性,所以我们需要封锁用户通过alloc和init以及copy来构造对象的这条路。
在创建对象的时候主要分这么两步 alloc (申请内存)init(初始化)
1.我们在第一步alloc的会后就要对其进行拦截。当我们去调用alloc的时候,OC内部会调用allocWithZone
这个方法去申请内存,我们去覆写这个方法,然后在这个方法中调用之前的类方法,返单例对象,这样就能达到我们的目的了。
2.拷贝对象也是一样的,覆写copyWithZone
方法,然后在方法中去调用类方法,返回单例对象。(在覆写copyWithZone
方法之前别忘记了签署NSCopying
协议)
类方法中也有做些许改动
#import <Foundation/Foundation.h>
@interface Singleton : NSObject<NSCopying>
+(instancetype)sharedInstance;
@end
#import "Singleton.h"
@implementation Singleton
static Singleton *instance = nil;
+(instancetype)sharedInstance{
static dispatch_once_t onceToken;
dispatch_once(&onceToken,^{
// instance = [[self alloc]init];
instance = [[super allocWithZone:NULL]init];
});
return instance;
}
+(id)allocWithZone:(struct _NSZone *)zone{
return [Singleton sharedInstance];
}
-(id)copyWithZone:(NSZone *)zone{
return [Singleton sharedInstance];
}
@end
接下来我们再看看通过不同方式创建之后的地址是否相同
控制台的输出
声明
本人并不是一个技术大神,只是一个菜鸟而已,写这个文章也不是为了炫耀什么,只是记录一下自己工作中的问题&如何解决。