1.单利模式概述

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

2.使用GCD实现单利模式

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

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

打印结果

  1. 使用GCD实现单利模式[2334:607] <HMDataTool: 0x8f064c0> <HMDataTool: 0x8f064c0> <HMDataTool: 0x8f064c0> <HMDataTool: 0x8f064c0>

3.非ARC实现单例模式

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

  1. - (oneway void)release { }
  2. - (id)retain { return self; }
  3. - (NSUInteger)retainCount { return 1;}
  4. - (id)autorelease { return self;}

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

 
  1. //  HMDataTool.h
  2. #import <Foundation/Foundation.h>
  3. @interface HMDataTool : NSObject
  4. + (instancetype)sharedDataTool;
  5. @end
  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. #import "HMDataTool.h"
  9. @implementation HMDataTool
  10. // 用来保存唯一的单例对象
  11. static id _instace;
  12. + (id)allocWithZone:(struct _NSZone *)zone
  13. {
  14. static dispatch_once_t onceToken;
  15. dispatch_once(&onceToken, ^{
  16. _instace = [super allocWithZone:zone];
  17. });
  18. return _instace;
  19. }
  20. + (instancetype)sharedDataTool
  21. {
  22. static dispatch_once_t onceToken;
  23. dispatch_once(&onceToken, ^{
  24. _instace = [[self alloc] init];
  25. });
  26. return _instace;
  27. }
  28. - (id)copyWithZone:(NSZone *)zone
  29. {
  30. return _instace;
  31. }
  32. /**
  33. *  重写下面几个关于引用计数器的方法就可以防止修改引用计数器的值,
  34. 这样就可以这个对象永远停留在内存中(因为这几个方法都是空的,所以尽管怎么调用,都没有作用)
  35. *
  36. *  @return <#return value description#>
  37. */
  38. - (oneway void)release { }
  39. - (id)retain { return self; }
  40. - (NSUInteger)retainCount { return 1;}
  41. - (id)autorelease { return self;}
  42. @end
  1. //
  2. //  HMViewController.h
  3. #import <UIKit/UIKit.h>
  4. @interface HMViewController : UIViewController
  5. @end
  1. //
  2. //  HMViewController.m
  3. #import "HMViewController.h"
  4. #import "HMDataTool.h"
  5. @interface HMViewController ()
  6. @end
  7. @implementation HMViewController
  8. - (void)viewDidLoad
  9. {
  10. [super viewDidLoad];
  11. HMDataTool *tool1 = [[HMDataTool alloc] init];
  12. HMDataTool *tool2 = [[HMDataTool alloc] init];
  13. HMDataTool *tool3 = [HMDataTool sharedDataTool];
  14. HMDataTool *tool4 = [HMDataTool sharedDataTool];
  15. /**
  16. *  重写了下面几个方法之后,则随便释放N次都没有用了
  17. - (oneway void)release { }
  18. - (id)retain { return self; }
  19. - (NSUInteger)retainCount { return 1;}
  20. - (id)autorelease { return self;}
  21. */
  22. [tool4 autorelease];
  23. [tool4 autorelease];
  24. [tool4 autorelease];
  25. [tool4 autorelease];
  26. [tool4 autorelease];
  27. NSLog(@"%@ %@ %@ %@", tool1, tool2, tool3, tool4);
  28. }<pre name="code" class="objc">+(loginModel *)sharedloginModel
  29. {
  30. static loginModel *loginmodle = nil;
  31. @synchronized(self)
  32. {
  33. if (loginmodle == nil) {
  34. loginmodle = [[loginModel alloc] init];
  35. }
  36. }
  37. return loginmodle;
  38. }

@end

运行结果

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

 

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

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

线程锁实现单粒
  1. +(Muser *)sharedMuser
  2. {
  3. staticstatic *user = nil;
  4. @synchronized(self)
  5. {
  6. if (user == nil) {
  7. user = [[Muser alloc] init];
  8. }
  9. }
  10. return user;
  11. }

GCD实现单粒

  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文件中得这个地方包含进去即可
单例模式——使用GCD实现单例模式 &amp; 非ARC单例模式 &amp;使用GCD和线程锁实现单例模式-b-LMLPHP
单例模式——使用GCD实现单例模式 &amp; 非ARC单例模式 &amp;使用GCD和线程锁实现单例模式-b-LMLPHP
  1. // .h文件 shared##name 是让前面HMSingletonH(name) 接收到的参数拼接起来
  2. #define HMSingletonH(name) + (instancetype)shared##name;
  3. // .m文件  如果是ARC
  4. #if __has_feature(objc_arc)
  5. #define HMSingletonM(name) \
  6. static id _instace; \
  7. \
  8. + (id)allocWithZone:(struct _NSZone *)zone \
  9. { \
  10. static dispatch_once_t onceToken; \
  11. dispatch_once(&onceToken, ^{ \
  12. _instace = [super allocWithZone:zone]; \
  13. }); \
  14. return _instace; \
  15. } \
  16. \
  17. + (instancetype)shared##name \
  18. { \
  19. static dispatch_once_t onceToken; \
  20. dispatch_once(&onceToken, ^{ \
  21. _instace = [[self alloc] init]; \
  22. }); \
  23. return _instace; \
  24. } \
  25. \
  26. - (id)copyWithZone:(NSZone *)zone \
  27. { \
  28. return _instace; \
  29. }
  30. //如果是非ARC
  31. #else
  32. #define HMSingletonM(name) \
  33. static id _instace; \
  34. \
  35. + (id)allocWithZone:(struct _NSZone *)zone \
  36. { \
  37. static dispatch_once_t onceToken; \
  38. dispatch_once(&onceToken, ^{ \
  39. _instace = [super allocWithZone:zone]; \
  40. }); \
  41. return _instace; \
  42. } \
  43. \
  44. + (instancetype)shared##name \
  45. { \
  46. static dispatch_once_t onceToken; \
  47. dispatch_once(&onceToken, ^{ \
  48. _instace = [[self alloc] init]; \
  49. }); \
  50. return _instace; \
  51. } \
  52. \
  53. - (id)copyWithZone:(NSZone *)zone \
  54. { \
  55. return _instace; \
  56. } \
  57. \
  58. - (oneway void)release { } \
  59. - (id)retain { return self; } \
  60. - (NSUInteger)retainCount { return 1;} \
  61. - (id)autorelease { return self;}
  62. #endif
  1. //
  2. //  HMViewController.m
  3. //
  4. #import "HMViewController.h"
  5. #import "HMMusicTool.h"
  6. #import "HMMovieTool.h"
  7. #import "HMDataTool.h"
  8. #import "HMPerson.h"
  9. @interface HMViewController ()
  10. @end
  11. @implementation HMViewController
  12. - (void)viewDidLoad
  13. {
  14. [super viewDidLoad];
  15. //    HMMusicTool *tool1 = [HMMusicTool sharedMusicTool];
  16. //    HMMusicTool *tool2 = [HMMusicTool sharedMusicTool];
  17. //
  18. //    HMMovieTool *tool3 = [HMMovieTool sharedMovieTool];
  19. //    HMMovieTool *tool4 = [HMMovieTool sharedMovieTool];
  20. //
  21. //    HMDataTool *tool5 = [HMDataTool sharedDataTool];
  22. //    HMDataTool *tool6 = [HMDataTool sharedDataTool];
  23. //
  24. //    NSLog(@"%@ %@", tool5, tool6);
  25. HMPerson *p = [[HMPerson alloc] init];
  26. #if __has_feature(objc_arc)
  27. // 编译器是ARC环境
  28. #else
  29. // 编译器是MRC环境
  30. [p release];
  31. #endif
  32. }
  33. @end

 
为什么使用宏?
这样可以方便项目中的其它单例的创建,只需要在项目中包含即可共用,而不必要再次用代码为每一个单例对象实现单例
04-16 00:52