美文网首页
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通用单例模式

相关文章

  • 单例

    iOS单例模式iOS之单例模式初探iOS单例详解

  • OC单例模式详解

    单例模式 有时候我们需要一个全局的对象,而且要保证全局有且仅有一份即可,这时候就需要用到单例设计模式,但是需要注意...

  • 设计模式之单例模式详解

    设计模式之单例模式详解 单例模式写法大全,也许有你不知道的写法 导航 引言 什么是单例? 单例模式作用 单例模式的...

  • iOS-单例模式

    swift的单例设计模式 OC的单例设计模式 新学习一种单例思想

  • iOS 单例模式

    关于单例模式的详解,看完这几篇,就完全了然了。iOS 单例模式iOS中的单例模式iOS单例的写法

  • 单例模式

    单例模式及C++实现代码单例模式4种实现详解 c++11改进我们的模式之改进单例模式 单例模式(Singleton...

  • 单例模式安全之反射攻击

    单例模式安全之反射攻击 源码 单例模式这里就不谈了,什么是单例模式可参考七种Java单例模式详解,这里是关于单例模...

  • Java架构师课程

    Java架构班开学典礼 Spring中常用的设计模式概述及工厂模式详解 单例模式及原型模式单例模式及原型模式单例模...

  • iOS模式解析-单例模式

    设计模式-单例模式 1、为什么用单例模式 1.1、OC编程习惯 xcode 4.2之前使用MRCalloc创建的对...

  • 高并发编程-04-线程安全-单例模式详解

    单例模式详解 1,编写单例模式 饿汉式:不会存在线程安全的问题 public class Singleton1 {...

网友评论

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

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