美文网首页
OC单例模式详解

OC单例模式详解

作者: Coder_Cat | 来源:发表于2018-02-01 16:07 被阅读33次

    单例模式

    有时候我们需要一个全局的对象,而且要保证全局有且仅有一份即可,这时候就需要用到单例设计模式,但是需要注意的是:在多线程的环境下也需要做好线程保护。其实系统已经有很多单例存在,例如UIApplication、NSNotification、NSFileManager、NSUserDefaults等.以下代码详解

    ARC环境下严谨的单例模式

    #import <Foundation/Foundation.h>
    @interface JHTool : NSObject<NSCopying,NSMutableCopying>
    //类方法
    //1.方便访问
    //2.标明身份
    //3.注意:share+类名|default + 类名 | share | default | 类名
    +(instancetype)shareTool;
    @end
    
    #import "JHTool.h"
    @implementation JHTool
    //提供一个全局静态变量
    static JHTool * _instance;
    
    +(instancetype)shareTool{
        return [[self alloc]init];
    }
    
    //当调用alloc的时候会调用allocWithZone
    +(instancetype)allocWithZone:(struct _NSZone *)zone{
        //方案一:加互斥锁,解决多线程访问安全问题
    //    @synchronized(self){//同步的
    //        if (!_instance) {
    //            _instance = [super allocWithZone:zone];
    //        }
    //    }
        //方案二.GCD dispatch_onec,本身是线程安全的,保证整个程序中只会执行一次
        static dispatch_once_t onceToken;
        dispatch_once(&onceToken, ^{
            _instance = [super allocWithZone:zone];
        });
        return _instance;
    }
    //严谨
    //遵从NSCopying协议,可以通过copy方式创建对象
    - (nonnull id)copyWithZone:(nullable NSZone *)zone {
        return _instance;
    }
    //遵从NSMutableCopying协议,可以通过mutableCopy方式创建对象
    - (nonnull id)mutableCopyWithZone:(nullable NSZone *)zone {
        return _instance;
    }
    @end
    
    #import "ViewController.h"
    #import "JHTool.h"
    
    @interface ViewController ()
    
    @end
    
    @implementation ViewController
    
    - (void)viewDidLoad {
        [super viewDidLoad];
        self.view.backgroundColor = [UIColor redColor];
        JHTool * tool1 = [[JHTool alloc]init];
        JHTool * tool2 = [JHTool shareTool];
        JHTool * tool3 = tool1.copy;
        JHTool * tool4 = tool2.mutableCopy;
        NSLog(@"tool1:%p,tool2:%p,tool3:%p,tool4:%p,",tool1,tool2,tool3,tool4);
        printf("tool1:%p,tool2:%p,tool3:%p,tool4:%p,",tool1,tool2,tool3,tool4);
        
    }
    @end
    

    打印结果:


    ARC单例模式

    MRC环境下严谨的单例模式

    Xcode5以后项目默认都是ARC,所以把项目设置成MRC环境,选择项目 Target -> Build Sttings -> All -> 搜索‘Automatic’ -> 把 Objective-C Automatic Reference Counting 设置为 NO ,如下图:


    项目设置成MRC环境

    MRC单例模式代码详解

    #import <Foundation/Foundation.h>
    @interface HJTool : NSObject<NSCopying,NSMutableCopying>
    //类方法
    +(instancetype)shareTool;
    @end
    
    #import "HJTool.h"
    
    @implementation HJTool
    //修改环境为MRC:选择项目 Target -> Build Sttings -> All -> 搜索‘Automatic’ -> 把 Objective-C Automatic Reference Counting 设置为 NO
    //提供一个静态全局变量
    static HJTool * _instance;
    //实现类方法
    +(instancetype)shareTool{
        return [[self alloc]init];
    }
    //alloc会调用allocWithZone
    +(instancetype)allocWithZone:(struct _NSZone *)zone{
        //方法一.互斥锁保证线程安全
    //    @synchronized(self){
    //        if (_instance == nil) {
    //            _instance = [super allocWithZone:zone];
    //        }
    //    }
        //方法一.GCD-> dispatch_once_t 该方法只会执行一次,本身线程安全
        static dispatch_once_t onceToken;
        dispatch_once(&onceToken, ^{
            _instance = [super allocWithZone:zone];
        });
        return _instance;
    }
    -(id)copyWithZone:(NSZone *)zone{
        return _instance;
    }
    -(id)mutableCopyWithZone:(NSZone *)zone{
        return _instance;
    }
    //MRC特有的
    -(instancetype)retain{
        return _instance;
    }
    -(oneway void)release{
        NSLog(@"%zd",_instance.retainCount);
    }
    
    #import "ViewController.h"
    #import "HJTool.h"
    
    @interface ViewController ()
    
    @end
    
    @implementation ViewController
    
    - (void)viewDidLoad {
        [super viewDidLoad];
        self.view.backgroundColor = [UIColor yellowColor];
    }
    - (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
        HJTool * t1 = [[HJTool alloc]init];
        HJTool * t2 = [[HJTool alloc]init];
        HJTool * t3 = [HJTool shareTool];
        HJTool * t4 = [t1 copy];
        HJTool * t5 = [t2 mutableCopy];
        HJTool * t6 = [t1 retain];
        NSLog(@"t6.retainCount : %zd",t1.retainCount);
        NSLog(@"t1:%p t2:%p t3:%p t4:%p t5:%p t6:%p",t1,t2,t3,t4,t5,t6);
    }
    

    打印结果


    MRC单例模式

    拓展:区分是MRC还是ARC的宏

    #if __has_feature(objc_arc)
        //条件满足 ARC,可以处理ARC的代码
        NSLog(@"ARC");
    #else
        //条件满足 MRC,,可以处理MRC的代码
        NSLog(@"MRC");
    #endif
    

    通用的单例模式

    SingleDog.h文件中定义一个宏, SingleH(name)定义单例.h文件的类方法声明,SingleM(name)定义和实现单例.m文件的方法,定义的宏的代码如下

    #define SingleH(name) +(instancetype)share##name;//.h文件替换
    //.m文件替换
    #if __has_feature(objc_arc)//arc
    //条件满足 ARC
    #define SingleM(name) static id _instance;\
    +(instancetype)allocWithZone:(struct _NSZone *)zone\
    {\
    static dispatch_once_t onceToken;\
    dispatch_once(&onceToken, ^{\
    _instance = [super allocWithZone:zone];\
    });\
    \
    return _instance;\
    }\
    \
    +(instancetype)share##name\
    {\
    return [[self alloc]init];\
    }\
    \
    -(id)copyWithZone:(NSZone *)zone\
    {\
    return _instance;\
    }\
    \
    -(id)mutableCopyWithZone:(NSZone *)zone\
    {\
    return _instance;\
    }
    
    #else
    //条件满足 MRC
    #define SingleM(name) static id _instance;\
    +(instancetype)allocWithZone:(struct _NSZone *)zone\
    {\
    static dispatch_once_t onceToken;\
    dispatch_once(&onceToken, ^{\
    _instance = [super allocWithZone:zone];\
    });\
    \
    return _instance;\
    }\
    \
    +(instancetype)share##name\
    {\
    return [[self alloc]init];\
    }\
    \
    -(id)copyWithZone:(NSZone *)zone\
    {\
    return _instance;\
    }\
    \
    -(id)mutableCopyWithZone:(NSZone *)zone\
    {\
    return _instance;\
    }\
    -(oneway void)release\
    {\
    }\
    \
    -(instancetype)retain\
    {\
    return _instance;\
    }
    #endif
    

    单例SingleTool文件,头文件和实现文件分别调用宏的SingleH(name),SingleM(name)即可,代码如下

    #import <Foundation/Foundation.h>
    #import "SingleDog.h"
    
    @interface SingleTool : NSObject
    //替换头文件
    SingleH(SingleTool)
    
    @end
    
    #import "SingleTool.h"
    
    @implementation SingleTool
    SingleM(SingleTool)
    @end
    
    #import "ViewController.h"
    #import "SingleTool.h"
    
    @interface ViewController ()
    
    @end
    
    @implementation ViewController
    
    -(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
        SingleTool * t1 = [[SingleTool alloc]init];
        SingleTool * t2 = [SingleTool shareSingleTool];
        SingleTool * t3 = [t1 copy];
        SingleTool * t4 = [t1 mutableCopy];
    #if __has_feature(objc_arc)
        //条件满足 ARC,可以处理ARC的代码
        NSLog(@"ARC");
    #else
        //条件满足 MRC,,可以处理MRC的代码
        NSLog(@"MRC");
        SingleTool * t5 = [t1 retain];
        NSLog(@"t6.retainCount : %zd",t1.retainCount);
        NSLog(@"t1:%p t2:%p t3:%p t4:%p t5:%p",t1,t2,t3,t4,t5);
    #endif
    }
    
    @end
    

    MRC环境下打印结果如下:


    MRC通用单例模式

    相关文章

      网友评论

          本文标题:OC单例模式详解

          本文链接:https://www.haomeiwen.com/subject/orwdzxtx.html