OC单例模式详解 左手的ㄟ右手 2022-05-12 05:34 293阅读 0赞 * * * [单例模式][Link 1] * [ARC环境下严谨的单例模式][ARC] * [MRC环境下严谨的单例模式][MRC] * [拓展:区分是MRC还是ARC的宏][MRC_ARC] * [通用的单例模式][Link 2] ### 单例模式 ### 有时候我们需要一个全局的对象,而且要保证全局有且仅有一份即可,这时候就需要用到单例设计模式,但是需要注意的是:在多线程的环境下也需要做好线程保护。其实系统已经有很多单例存在,例如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][ARC 1] MRC环境下严谨的单例模式 Xcode5以后项目默认都是ARC,所以把项目设置成MRC环境,选择项目 Target -> Build Sttings -> All -> 搜索‘Automatic’ -> 把 Objective-C Automatic Reference Counting 设置为 NO ,如下图: ![项目设置成MRC环境][MRC 1] 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); } > 打印结果 > ![这里写图片描述][SouthEast] 拓展:区分是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éç¨åä¾æ¨¡å¼][MRC 2] [Link 1]: https://blog.csdn.net/bolted_snail/article/details/79230097#%E5%8D%95%E4%BE%8B%E6%A8%A1%E5%BC%8F [ARC]: https://blog.csdn.net/bolted_snail/article/details/79230097#arc%E7%8E%AF%E5%A2%83%E4%B8%8B%E4%B8%A5%E8%B0%A8%E7%9A%84%E5%8D%95%E4%BE%8B%E6%A8%A1%E5%BC%8F [MRC]: https://blog.csdn.net/bolted_snail/article/details/79230097#mrc%E7%8E%AF%E5%A2%83%E4%B8%8B%E4%B8%A5%E8%B0%A8%E7%9A%84%E5%8D%95%E4%BE%8B%E6%A8%A1%E5%BC%8F [MRC_ARC]: https://blog.csdn.net/bolted_snail/article/details/79230097#%E6%8B%93%E5%B1%95%E5%8C%BA%E5%88%86%E6%98%AFmrc%E8%BF%98%E6%98%AFarc%E7%9A%84%E5%AE%8F [Link 2]: https://blog.csdn.net/bolted_snail/article/details/79230097#%E9%80%9A%E7%94%A8%E7%9A%84%E5%8D%95%E4%BE%8B%E6%A8%A1%E5%BC%8F [ARC 1]: /images/20220512/b967e245c0fe4e029a447d94a9f6c22f.png [MRC 1]: /images/20220512/e075d73509354abebc3f2f88dae7e091.png [SouthEast]: /images/20220512/3b4c9ceb20a14df3b3aac62946d42504.png [MRC 2]: /images/20220512/64f7295d1bbf486d95fe0ad3dd0a7065.png
相关 单例模式详解! 1.懒汉式(线程不安全) //懒汉式创建单例模式 public class Singleton { private static Single 你的名字/ 2024年01月20日 07:35/ 0 赞/ 21 阅读
相关 单例模式详解 一、概述 单例模式的定义就是确保某一个类只有一个实例,并且提供一个全局访问点 单例模式具有典型的三个特点: > 只有一个实例。 > 自我实例化。 > 布满荆棘的人生/ 2023年02月20日 12:21/ 0 赞/ 54 阅读
相关 单例模式详解 http://www.cnblogs.com/zuoxiaolong/p/pattern2.html 上一章,我们学习了设计模式的概念,以及为什么要学习设计模式,还 布满荆棘的人生/ 2022年09月25日 15:30/ 0 赞/ 236 阅读
相关 【iOS提高】单例模式在OC的使用 有三种方法可以保证当前的程序中只有一个对象实例。 1.GCD +(instancetype)sharedInstance2 { static 本是古典 何须时尚/ 2022年08月20日 09:16/ 0 赞/ 237 阅读
相关 OC单例写法 // // SingeTest.h // OC基础学习 // // Created by 麦子 on 15/5/29. / 电玩女神/ 2022年08月05日 02:40/ 0 赞/ 221 阅读
相关 单例模式详解 什么是单例设计模式:在应用程序中,只能存在某类的一个实例对象 1)分类: 1 懒汉式 a)private static 该类的变量名; b 柔情只为你懂/ 2022年06月12日 07:20/ 0 赞/ 200 阅读
相关 单例模式详解 单例模式 单例模式(Singleton Pattern)是 Java 中最简单的设计模式之一。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。 这种模 清疚/ 2022年05月12日 13:28/ 0 赞/ 244 阅读
相关 单例模式详解 本文主要分享的内容是单例模式的应用场景、常见的单例模式写法、保证线程安全的单例模式策略、反射暴力攻击单例解决方案及原理分析、序列化破坏单例的原理及解决方案。 一、单 小鱼儿/ 2022年02月14日 11:29/ 0 赞/ 308 阅读
相关 设计模式详解-单例模式详解 [2019独角兽企业重金招聘Python工程师标准>>> ][2019_Python_] ![hot3.png][] 在我的工作过程中,我发现所有可以使用单例模式的类都有一个 素颜马尾好姑娘i/ 2022年01月14日 14:39/ 0 赞/ 343 阅读
还没有评论,来说两句吧...