首页 > 代码库 > iOS开发多线程篇—单例模式(MRC)
iOS开发多线程篇—单例模式(MRC)
iOS开发多线程篇—单例模式(MRC)
一、非ARC模式下的单例模式
1.说明:把一个项目修改为非ARC的
2.MAC下单例模式代码示例:
新建一个工具类,让该类继承自NSObject。
YYAudioTool.m文件
1 // 2 // YYAudioTool.m 3 // 06-单例模式1 4 // 5 // Created by apple on 14-6-25. 6 // Copyright (c) 2014年 itcase. All rights reserved. 7 // 8 9 #import "YYAudioTool.h"10 @interface YYAudioTool ()11 //用来保存mp3文件12 @property(nonatomic,strong)NSMutableDictionary *muscis;13 @end14 15 @implementation YYAudioTool16 //定义一份变量(整个程序运行过程中,只有一份)17 static id _instace;18 //单例模式:设计19 //(1)永远只分配一块内存来创建对象20 //(2)提供一个类方法,返回内部唯一的一个变量21 //(3)最好保证init方法也只初始化一次22 23 //构造方法24 -(id)init25 {26 // __block id obj=nil;27 static id obj=nil;28 static dispatch_once_t onceToken;29 dispatch_once(&onceToken, ^{30 if ((obj=[super init]) != nil) {31 32 }33 });34 self=obj;35 36 return self;37 }38 39 40 //重写该方法,控制内存的分配,永远只分配一次存储空间41 +(id)allocWithZone:(struct _NSZone *)zone42 {43 44 //里面的代码只会执行一次45 static dispatch_once_t onceToken;46 dispatch_once(&onceToken, ^{47 _instace=[super allocWithZone:zone];48 });49 return _instace;50 }51 52 //类方法53 +(id)sharedAudioTool54 {55 //里面的代码永远都只执行一次56 static dispatch_once_t onceToken;57 dispatch_once(&onceToken, ^{58 _instace=[[self alloc]init];59 });60 return _instace;61 }62 63 //重写release方法64 //oneway :分布式对象65 -(oneway void)release66 {67 }68 69 //不管调用哪个方法,返回的都是唯一的实例,所以这里self和instace是一样的70 -(id)autorelease71 {72 return self;73 }74 75 -(id)retain76 {77 return self;78 }79 80 -(NSUInteger)retainCount81 {82 return 1;83 }84 85 +(id)copyWithZone:(struct _NSZone *)zone86 {87 return _instace;88 }89 @end
YYAudioTool.h文件
1 // 2 // YYAudioTool.h 3 // 06-单例模式1 4 // 5 // Created by apple on 14-6-25. 6 // Copyright (c) 2014年 itcase. All rights reserved. 7 // 8 9 #import <Foundation/Foundation.h>10 11 @interface YYAudioTool : NSObject12 //提供一个类方法,返回内部唯一的一个变量13 +(id)sharedAudioTool;14 @end
主控制器中创建对象:
1 // 2 // YYViewController.m 3 // 06-单例模式1 4 // 5 // Created by apple on 14-6-25. 6 // Copyright (c) 2014年 itcase. All rights reserved. 7 // 8 9 #import "YYViewController.h"10 #import "YYAudioTool.h"11 12 @interface YYViewController ()13 14 @end15 16 @implementation YYViewController17 18 - (void)viewDidLoad19 {20 [super viewDidLoad];21 YYAudioTool *tool1=[YYAudioTool sharedAudioTool];22 YYAudioTool *tool2=[YYAudioTool sharedAudioTool];23 YYAudioTool *tool3=[YYAudioTool sharedAudioTool];24 YYAudioTool *tool4=[[YYAudioTool alloc]init];25 26 NSLog(@"%p--%p--%p--%p",tool1,tool2,tool3,tool4);27 28 //对象创建只会,release对象会销毁,无法再创建新的对象(因为单例),所以还需要重写release方法29 [tool1 release];30 [tool2 release];31 [tool3 release];32 [tool4 release];33 }34 35 @end
打印结果:
说明:整个程序过程中,只创建一个对象实例。
二、把单例代码定义为一个带参数的宏
1.新的困扰
弊端:如果又创建一个新的类,是否又要把文件代码拷贝一份,所以这里可以考虑把固定的代码写成宏。
由于项目中代码经常有移植的需要,要求项目中又有ARC的,又有非ARC的,应该怎么应用单例模式?
不管项目是ARC的还是非ARC的,这个宏都有用。可以先判断编译器的环境,判断当前环境是否是ARC的。
条件编译的使用:
2.使用条件编译,并把单例模式的代码定义为宏。
新建一个.h头文件
把代码定义为宏,头文件中的代码如下:
1 // ## : 连接字符串和参数 2 #define singleton_h(name) + (instancetype)shared##name; 3 4 #if __has_feature(obj_arc) //如果是ARC 5 #define singleton_m(name) 6 static id _instance; 7 + (id)allocWithZone:(struct _NSZone *)zone 8 { 9 static dispatch_once_t onceToken; 10 dispatch_once(&onceToken, ^{ 11 _instance = [super allocWithZone:zone]; 12 }); 13 return _instance; 14 } 15 16 + (instancetype)shared##name 17 { 18 static dispatch_once_t onceToken; 19 dispatch_once(&onceToken, ^{ 20 _instance = [[self alloc] init]; 21 }); 22 return _instance; 23 } 24 25 + (id)copyWithZone:(struct _NSZone *)zone 26 { 27 return _instance; 28 }29 30 #else //非ARC31 #define singleton_m(name) 32 static id _instance; 33 + (id)allocWithZone:(struct _NSZone *)zone 34 { 35 static dispatch_once_t onceToken; 36 dispatch_once(&onceToken, ^{ 37 _instance = [super allocWithZone:zone]; 38 }); 39 return _instance; 40 } 41 42 + (instancetype)shared##name 43 { 44 static dispatch_once_t onceToken; 45 dispatch_once(&onceToken, ^{ 46 _instance = [[self alloc] init]; 47 }); 48 return _instance; 49 } 50 51 - (oneway void)release 52 { 53 54 } 55 56 - (id)autorelease 57 { 58 return _instance; 59 } 60 61 - (id)retain 62 { 63 return _instance; 64 } 65 66 - (NSUInteger)retainCount 67 { 68 return 1; 69 } 70 71 + (id)copyWithZone:(struct _NSZone *)zone 72 { 73 return _instance; 74 }75 #endif
在程序中的应用:
控制器问价代码如下:
1 #import "YYViewController.h" 2 #import "YYAudioTool.h" 3 4 @interface YYViewController () 5 6 @end 7 8 @implementation YYViewController 9 10 - (void)viewDidLoad11 {12 [super viewDidLoad];13 YYAudioTool *tool1=[YYAudioTool sharedAudioTool];14 15 //对象创建后,需要考虑16 // (1)alloc init17 // (2)release18 // (3)copy copy内部会调用另外一个方法copywithzone19 // (4)autorelease20 // 21 YYAudioTool *tool2=[YYAudioTool sharedAudioTool];22 YYAudioTool *tool3=[YYAudioTool sharedAudioTool];23 NSLog(@"%p---%p---%p",tool1,tool2,tool3);24 [tool2 release];25 [tool3 release];26 [tool1 release];27 28 }29 30 @end
工具类的头文件代码如下:
1 // 2 // YYAudioTool.h 3 // 06-单例模式1 4 // 5 // Created by apple on 14-6-25. 6 // Copyright (c) 2014年 itcase. All rights reserved. 7 // 8 9 #import <Foundation/Foundation.h>10 #import "Singleton.h"11 12 @interface YYAudioTool : NSObject13 ////提供一个类方法,返回内部唯一的一个变量14 //+(id)sharedAudioTool;15 singleton_h(AudioTool)16 @end
工具类的实现部分代码如下:
1 // 2 // YYAudioTool.m 3 // 06-单例模式1 4 // 5 // Created by apple on 14-6-25. 6 // Copyright (c) 2014年 itcase. All rights reserved. 7 // 8 9 #import "YYAudioTool.h"10 @interface YYAudioTool ()11 //用来保存mp3文件12 @property(nonatomic,strong)NSMutableDictionary *muscis;13 @end14 15 @implementation YYAudioTool16 //定义一份变量(整个程序运行过程中,只有一份)17 //static id _instace;18 19 //构造方法20 -(id)init21 {22 // __block id obj=nil;23 static id obj=nil;24 static dispatch_once_t onceToken;25 dispatch_once(&onceToken, ^{26 if ((obj=[super init]) != nil) {27 //........28 }29 });30 self=obj;31 return self;32 }33 34 singleton_m(AudioTool)35 @end
补充说明:如果把代码下载dispatch_once里面,那么它内部默认会进行加锁。
三、补充
问题:ARC和非ARC单例模式的区别?
由于非ARC是进行手动内存管理,所以需要注意下面一个方法,在项目中通常使用宏。
- (id)retain { return self; }
- (NSUInteger)retainCount { return 1; }
- (oneway void)release {}
- (id)autorelease { return self; }
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。