ios~单例模式:

2022-03-30  本文已影响0人  阳光下的叶子呵

在iOS OC中,一般我们都是用官方推荐的写法来写单例:GCD方式单例


单例:整个程序只创建一次,全局共用。

1.  ****单例的创建****
// SharedPerson.h 文件中
+ (instancetype)share;

// SharedPerson.m 文件中
static SharedPerson *_person; 
+ (instancetype)allocWithZone:(struct _NSZone *)zone {
        static dispatch_once_t predicate;
        dispatch_once(&predicate, ^{
            _person = [super allocWithZone:zone];
        });
        return _person;  
} 

+ (instancetype)share {     
        static dispatch_once_t onceToken;
        dispatch_once(&onceToken, ^{
            _person = [[self alloc]init];
        }); 
        return _person;
} 
- (id)copyWithZone:(NSZone *)zone { 
      return _person;
}
  1. 分析单例
3、一般使用:
+ (instancetype)sharedInstance;
+ (instancetype)sharedInstance {
    static URLManager * ins = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        ins = [[URLManager alloc] init];
    });
    return ins;
}

URLManager* a = [URLManager sharedInstance];
接下来,可以用 a 这个单例来干很多事情了,看起来没有问题。在很多实际的项目中,很多人也的确是这么做的。

可是,谁能保证所有人都会使用 sharedInstance 方法来创建对象?而一旦有人用 alloc,new 等来创建对象,这就不是单例了。
例如:

    URLManager* a = [URLManager sharedInstance];
    URLManager* b = [[URLManager alloc] init];
    URLManager* c = [URLManager new];

查看 a、b、c :


截屏2022-03-30 14.59.30.png

可以看到,a、b、c 不是同一个对象,而所谓单例,就是不管我用何种方法创建对象,都必须是同一个
所以,单例模式,绝不是一个 sharedInstance 就够了。

解决方案 一
那么如何避免这种问题呢?我们知道:
在对象创建的时候,无论是 alloc 还是 new,都会调用到 allocWithZone: 方法;
使用拷贝创建对象时,会调用 copyWithZone:,mutableCopyWithZone:方法;
那么,重写这些方法,就可以让创建的对象唯一。

+ (instancetype)sharedInstance {
    static URLManager * ins = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        ins = [[super allocWithZone:nil] init];
    });
    return ins;
}

+(id)allocWithZone:(NSZone *)zone{
    return [self sharedInstance];
}
-(id)copyWithZone:(NSZone *)zone{
    return [[self class] sharedInstance];
}
-(id)mutableCopyWithZone:(NSZone *)zone{
    return [[self class] sharedInstance];
}

再运行,看一看a、b、c:


截屏2022-03-30 15.03.01.png

都是同一个对象!大功告成!

解决方案 二
此外,还有一种方法,就是直接禁用掉 alloc、new 、copy等方法:

+(instancetype) alloc __attribute__((unavailable("replace with 'sharedInstance'")));

+(instancetype) new __attribute__((unavailable("replace with 'sharedInstance'")));

-(instancetype) copy __attribute__((unavailable("replace with 'sharedInstance'")));

-(instancetype) mutableCopy __attribute__((unavailable("replace with 'sharedInstance'")));

如此,在调用这些方法时就会报错,提示使用 sharedInstance 方法:


截屏2022-03-30 15.04.45.png

以此,也可以达到单例模式的要求,始终只有一个对象。

上一篇 下一篇

猜你喜欢

热点阅读