iOS单例模式容错处理

ios 单例模式容错处理

1、单例模式的使用和问题解决

在ios开发的过程中,使用单例模式的场景非常多。系统也有很多单例提供给我们,比如:

  [UIApplication sharedApplication];
  [NSUserDefaults standardUserDefaults];

定义:保证一个类只有一个实例变量,并且提供一个全局的访问入口访问这个变量
一般用法:

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

1.1、问题

可是Objective-C毕竟是Objective-C。别的语言,诸如C++,java,构造方法可以隐藏。Objective-C中的方法,实际上都是公开的,虽然我们提供了一个方便的工厂方法的访问入口,但是里面的alloc方法依旧是可见的,可以调用到的。也就是说,虽然你给了我一个工厂方法,调皮的小伙伴可能依旧会使用alloc的方式创建对象。这样会导致外面使用的时候,依旧可能创建多个实例。

    //正确用法
    YYSingleton *singleton = [YYSingleton sharedInstance];

    //错误用法
    YYSingleton *singleton1 = [[YYSingleton alloc]init];
    YYSingleton *singleton2 = [YYSingleton new];
    YYSingleton *singleton3 = [singleton1 copy];
    YYSingleton *singleton3 = [singleton1 mutableCopy];

1.2、解决

关于这个事情的处理,可以分为两派。一个是冷酷派,技术上实现无论你怎么调用,我都给你同一个单例对象;一个是温柔派,是从编译器上给调皮的小伙伴提示,你不能这么造对象,温柔的指出有问题,但不强制约束。

1.2.1:冷酷派-内部强制实现

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

//调用alloc-init,new等方法(实质是调用allocWithZone)
+ (instancetype)allocWithZone:(struct _NSZone *)zone{
    return [YYSingleton sharedInstance];
}

//copy
- (id)copyWithZone:(NSZone *)zone{
    return [YYSingleton sharedInstance];
}

//mutableCopy
- (id)mutableCopyWithZone:(nullable NSZone *)zone{
    return [YYSingleton sharedInstance];
}

无论外部调用创建对象方法或者copy,mutableCopy,都返回[YYSingleton sharedInstance];

iOS单例模式容错处理_第1张图片
WechatIMG155.png

1.2.1:温柔派-外部提醒

这种解决办法在外部调用创建对象方法或者copy,mutableCopy时,报出❌警告提醒外部要使用单例调用方法,可以使用到宏定义来解决这个问题:

#define YY_SINGLETON_DEF(_type_) \
+ (_type_ *)sharedInstance;\
+(instancetype) alloc       __attribute__((unavailable("call sharedInstance instead")));\
+(instancetype) new         __attribute__((unavailable("call sharedInstance instead")));\
-(instancetype) copy        __attribute__((unavailable("call sharedInstance instead")));\
-(instancetype) mutableCopy __attribute__((unavailable("call sharedInstance instead")));

#define YY_SINGLETON_IMP(_type_)\
+ (_type_ *)sharedInstance{\
static _type_ *theSharedInstance = nil;\
static dispatch_once_t onceToken;\
dispatch_once(&onceToken, ^{\
theSharedInstance = [[super alloc] init];\
});\
return theSharedInstance;\
}

YYSingleton中代码:

.h

@interface YYSingleton : NSObject
//声明一个单例
YY_SINGLETON_DEF(singleton);
@end

.m

#import "YYSingleton.h"

@implementation YYSingleton
//实现单例
YY_SINGLETON_IMP(singleton);
@end

调用

 YYSingleton *Singleton = [YYSingleton sharedInstance];
iOS单例模式容错处理_第2张图片
示例.png

当调用除[YYSingleton sharedInstance]以外的方法时,都会报出错误;

你可能感兴趣的:(iOS单例模式容错处理)