单例模式——使用GCD实现单例模式 & 非ARC单例模式 &使用GCD和线程锁实现单例模式-b

1.单利模式概述

 链接:  iOS开发懒汉模式&恶寒模式

2.使用GCD实现单利模式

2.1新建一个project,然后新建一个HMDataTool类展示GCD实现单例模式

[objc] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. #import <Foundation/Foundation.h>  
  2.   
  3. @interface HMDataTool : NSObject  
  4. + (instancetype)sharedDataTool;  
  5. @end  
[objc] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. #import "HMDataTool.h"  
  2.   
  3. @implementation HMDataTool  
  4. // 用来保存唯一的单例对象  
  5. static id _instace;  
  6.   
  7. + (id)allocWithZone:(struct _NSZone *)zone  
  8. {  
  9.     static dispatch_once_t onceToken;  
  10.     dispatch_once(&onceToken, ^{   //onceToken是GCD用来记录是否执行过 ,如果已经执行过就不再执行(保证执行一次)  
  11.         _instace = [super allocWithZone:zone];  
  12.     });  
  13.     return _instace;  
  14. }  
  15.   
  16. + (instancetype)sharedDataTool  
  17. {  
  18.     static dispatch_once_t onceToken;  
  19.     dispatch_once(&onceToken, ^{  
  20.         _instace = [[self alloc] init];  
  21.     });  
  22.     return _instace;  
  23. }  
  24.   
  25. - (id)copyWithZone:(NSZone *)zone  
  26. {  
  27.     return _instace;  
  28. }  
  29.   
  30. @end  
[objc] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. #import "htingViewController.h"  
  2. #import"HMDataTool.h"  
  3. @interface htingViewController ()  
  4.   
  5. @end  
  6.   
  7. @implementation htingViewController  
  8.   
  9. - (void)viewDidLoad  
  10. {  
  11.     [super viewDidLoad];  
  12.     // Do any additional setup after loading the view, typically from a nib.  
  13.       
  14.         HMDataTool *tool1 = [HMDataTool sharedDataTool];  
  15.         HMDataTool *tool2 = [HMDataTool sharedDataTool];  
  16.         HMDataTool *tool3 = [[HMDataTool alloc] init];  
  17.         HMDataTool *tool4 = [[HMDataTool alloc] init];  
  18.       
  19.         NSLog(@"%@ %@ %@ %@", tool1, tool2, tool3, tool4);  
  20. }  
  21.   
  22.   
  23.   
  24. @end  


打印结果

[objc] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. 使用GCD实现单利模式[2334:607] <HMDataTool: 0x8f064c0> <HMDataTool: 0x8f064c0> <HMDataTool: 0x8f064c0> <HMDataTool: 0x8f064c0>  

3.非ARC实现单例模式

3.1非ARC内存管理模式下对象必须手动释放,为了防止那个唯一的单例对象被释放掉,则只需要重写下面的几个方法即可

[objc] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. - (oneway void)release { }  
  2. - (id)retain { return self; }  
  3. - (NSUInteger)retainCount { return 1;}  
  4. - (id)autorelease { return self;}  

3.2通过新建一个HMDataTool类来演示非ARC单例模式

 
[objc] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. //  HMDataTool.h  
  2.   
  3.   
  4. #import <Foundation/Foundation.h>  
  5.   
  6. @interface HMDataTool : NSObject  
  7. + (instancetype)sharedDataTool;  
  8. @end  
[objc] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. //  
  2. //  HMDataTool.m  
  3. //  03-单例模式-Singleton(掌握)  
  4. //  
  5. //  Created by apple on 14-9-16.  
  6. //  Copyright (c) 2014年 heima. All rights reserved.  
  7. //  
  8.   
  9. #import "HMDataTool.h"  
  10.   
  11. @implementation HMDataTool  
  12. // 用来保存唯一的单例对象  
  13. static id _instace;  
  14.   
  15. + (id)allocWithZone:(struct _NSZone *)zone  
  16. {  
  17.     static dispatch_once_t onceToken;  
  18.     dispatch_once(&onceToken, ^{  
  19.         _instace = [super allocWithZone:zone];  
  20.     });  
  21.     return _instace;  
  22. }  
  23.   
  24. + (instancetype)sharedDataTool  
  25. {  
  26.     static dispatch_once_t onceToken;  
  27.     dispatch_once(&onceToken, ^{  
  28.         _instace = [[self alloc] init];  
  29.     });  
  30.     return _instace;  
  31. }  
  32.   
  33. - (id)copyWithZone:(NSZone *)zone  
  34. {  
  35.     return _instace;  
  36. }  
  37. /** 
  38.  *  重写下面几个关于引用计数器的方法就可以防止修改引用计数器的值, 
  39.     这样就可以这个对象永远停留在内存中(因为这几个方法都是空的,所以尽管怎么调用,都没有作用) 
  40.  * 
  41.  *  @return <#return value description#> 
  42.  */  
  43.   
  44. - (oneway void)release { }  
  45. - (id)retain { return self; }  
  46. - (NSUInteger)retainCount { return 1;}  
  47. - (id)autorelease { return self;}  
  48.   
  49. @end  

[objc] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. //  
  2. //  HMViewController.h  
  3.   
  4.   
  5. #import <UIKit/UIKit.h>  
  6.   
  7. @interface HMViewController : UIViewController  
  8.   
  9. @end  

[objc] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. //  
  2. //  HMViewController.m  
  3.   
  4.   
  5.   
  6. #import "HMViewController.h"  
  7. #import "HMDataTool.h"  
  8.   
  9. @interface HMViewController ()  
  10.   
  11. @end  
  12.   
  13. @implementation HMViewController  
  14.   
  15. - (void)viewDidLoad  
  16. {  
  17.     [super viewDidLoad];  
  18.       
  19.     HMDataTool *tool1 = [[HMDataTool alloc] init];  
  20.     HMDataTool *tool2 = [[HMDataTool alloc] init];  
  21.     HMDataTool *tool3 = [HMDataTool sharedDataTool];  
  22.     HMDataTool *tool4 = [HMDataTool sharedDataTool];  
  23.     /** 
  24.      *  重写了下面几个方法之后,则随便释放N次都没有用了 
  25.      - (oneway void)release { } 
  26.      - (id)retain { return self; } 
  27.      - (NSUInteger)retainCount { return 1;} 
  28.      - (id)autorelease { return self;} 
  29.       
  30.      */  
  31.       [tool4 autorelease];  
  32.       [tool4 autorelease];  
  33.       [tool4 autorelease];  
  34.       [tool4 autorelease];  
  35.       [tool4 autorelease];  
  36.       
  37.     NSLog(@"%@ %@ %@ %@", tool1, tool2, tool3, tool4);  
  38. }<pre name="code" class="objc">+(loginModel *)sharedloginModel  
  39. {  
  40.     static loginModel *loginmodle = nil;  
  41.     @synchronized(self)  
  42.     {  
  43.         if (loginmodle == nil) {  
  44.             loginmodle = [[loginModel alloc] init];  
  45.         }  
  46.     }  
  47.       
  48.     return loginmodle;  
  49.       
  50. }  

@end

运行结果

单例模式-ARC(掌握)[2592:607] <HMDataTool: 0x8d12600> <HMDataTool: 0x8d12600> <HMDataTool: 0x8d12600> <HMDataTool: 0x8d12600>

 

4.线程锁和GCD实现单例模式

4.1线程锁和GCD实现单粒模式

线程锁实现单粒
[objc] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. +(Muser *)sharedMuser  
  2. {  
  3.     staticstatic *user = nil;  
  4.     @synchronized(self)  
  5.     {  
  6.         if (user == nil) {  
  7.             user = [[Muser alloc] init];  
  8.         }  
  9.     }  
  10.       
  11.     return user;  
  12.       
  13. }  
GCD实现单粒
[objc] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. +(<span style="font-family: Arial, Helvetica, sans-serif;">sharedsegMentTitles</span><span style="font-family: Arial, Helvetica, sans-serif;"> *</span><span style="font-family: Arial, Helvetica, sans-serif;">)sharedsegMentTitles</span>  
  2. {  
  3.     static SwitchMenuViewModel * segTitles = nil;  
  4.     static dispatch_once_t once;  
  5.     dispatch_once(&once,^{  
  6.    if (segTitles == nil) {  
  7.       segTitles = [[SwitchMenuViewModel alloc]init];  
  8.         }  
  9.     });  
  10.     return segTitles;  
  11. }  



4.2为什么使用宏?

 
假设一个项目中有多个类需要单例,则需要每个类都实现一遍单例,这样很繁琐,因此可以采用定义宏的方式,写一个单例文件添加到项目中然后在项目的Prefix.pch文件中得这个地方包含进去即可
[objc] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. // .h文件 shared##name 是让前面HMSingletonH(name) 接收到的参数拼接起来  
  2. #define HMSingletonH(name) + (instancetype)shared##name;  
  3.   
  4. // .m文件  如果是ARC  
  5. #if __has_feature(objc_arc)  
  6.   
  7.     #define HMSingletonM(name)   
  8.     static id _instace;   
  9.    
  10.     + (id)allocWithZone:(struct _NSZone *)zone   
  11.     {   
  12.         static dispatch_once_t onceToken;   
  13.         dispatch_once(&onceToken, ^{   
  14.             _instace = [super allocWithZone:zone];   
  15.         });   
  16.         return _instace;   
  17.     }   
  18.    
  19.     + (instancetype)shared##name   
  20.     {   
  21.         static dispatch_once_t onceToken;   
  22.         dispatch_once(&onceToken, ^{   
  23.             _instace = [[self alloc] init];   
  24.         });   
  25.         return _instace;   
  26.     }   
  27.    
  28.     - (id)copyWithZone:(NSZone *)zone   
  29.     {   
  30.         return _instace;   
  31.     }  
  32. //如果是非ARC  
  33. #else  
  34.   
  35.     #define HMSingletonM(name)   
  36.     static id _instace;   
  37.    
  38.     + (id)allocWithZone:(struct _NSZone *)zone   
  39.     {   
  40.         static dispatch_once_t onceToken;   
  41.         dispatch_once(&onceToken, ^{   
  42.             _instace = [super allocWithZone:zone];   
  43.         });   
  44.         return _instace;   
  45.     }   
  46.    
  47.     + (instancetype)shared##name   
  48.     {   
  49.         static dispatch_once_t onceToken;   
  50.         dispatch_once(&onceToken, ^{   
  51.             _instace = [[self alloc] init];   
  52.         });   
  53.         return _instace;   
  54.     }   
  55.    
  56.     - (id)copyWithZone:(NSZone *)zone   
  57.     {   
  58.         return _instace;   
  59.     }   
  60.    
  61.     - (oneway void)release { }   
  62.     - (id)retain { return self; }   
  63.     - (NSUInteger)retainCount { return 1;}   
  64.     - (id)autorelease { return self;}  
  65.   
  66. #endif  
[objc] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. //  
  2. //  HMViewController.m  
  3. //    
  4. #import "HMViewController.h"  
  5. #import "HMMusicTool.h"  
  6. #import "HMMovieTool.h"  
  7. #import "HMDataTool.h"  
  8.   
  9. #import "HMPerson.h"  
  10.   
  11. @interface HMViewController ()  
  12.   
  13. @end  
  14.   
  15. @implementation HMViewController  
  16.   
  17. - (void)viewDidLoad  
  18. {  
  19.     [super viewDidLoad];  
  20.       
  21. //    HMMusicTool *tool1 = [HMMusicTool sharedMusicTool];  
  22. //    HMMusicTool *tool2 = [HMMusicTool sharedMusicTool];  
  23. //  
  24. //    HMMovieTool *tool3 = [HMMovieTool sharedMovieTool];  
  25. //    HMMovieTool *tool4 = [HMMovieTool sharedMovieTool];  
  26. //      
  27. //    HMDataTool *tool5 = [HMDataTool sharedDataTool];  
  28. //    HMDataTool *tool6 = [HMDataTool sharedDataTool];  
  29. //  
  30. //    NSLog(@"%@ %@", tool5, tool6);  
  31.       
  32.     HMPerson *p = [[HMPerson alloc] init];  
  33.       
  34. #if __has_feature(objc_arc)  
  35.     // 编译器是ARC环境  
  36. #else  
  37.     // 编译器是MRC环境  
  38.     [p release];  
  39. #endif  
  40. }  
  41.   
  42. @end  



 
为什么使用宏?
这样可以方便项目中的其它单例的创建,只需要在项目中包含即可共用,而不必要再次用代码为每一个单例对象实现单例
原文地址:https://www.cnblogs.com/isItOk/p/5598483.html