# 單例模式(面試必考)面試
static id _instance;
+ (instancetype)allocWithZone:(struct _NSZone *)zone { static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ _instance = [super allocWithZone:zone]; }); return _instance; }
+ (instancetype)sharedInstance { static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ _instance = [[self alloc] init]; }); return _instance; }
- (id)copyWithZone:(struct _NSZone *)zone { return _instance; }
static id _instance; + (instancetype)allocWithZone:(struct _NSZone *)zone { static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ _instance = [[super allocWithZone:zone] init]; // 記住這兒是super,不能用self }); return _instance; } + (instancetype)sharedPerson { static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ _instance = [[self alloc] init]; }); return _instance; } // copyWithZone方法的前提是必須先有一個對象 - (id)copyWithZone:(NSZone *)zone { return _instance; }
單例抽成一個宏放在一個單獨的.h文件中
,千萬不能用繼承
\
表示此行跟下面一行是一塊兒的##
表示後面是參數// .h文件中的聲明 #define SLInstanceH(name) + (instancetype)shared##name; // .m文件的實現 #define SLInstanceM(name) static id _instance; \ \ + (instancetype)allocWithZone:(struct _NSZone *)zone\ {\ static dispatch_once_t onceToken;\ dispatch_once(&onceToken, ^{\ _instance = [[super allocWithZone:zone] init];\ });\ return _instance;\ }\ \ + (instancetype)shared##name\ {\ static dispatch_once_t onceToken;\ dispatch_once(&onceToken, ^{\ _instance = [[self alloc] init];\ });\ return _instance;\ }\ \ - (id)copyWithZone:(NSZone *)zone\ {\ return _instance;\ }
#import <Foundation/Foundation.h> #import "SLSharedInstance.h" // 導入,定義了宏的.h文件 @interface SLPerson : NSObject<NSCopying> SLInstanceH(Person) // 傳入單例的對象 @end
#import "SLPerson.h" @implementation SLPerson SLInstanceM(Person) @end
#import "SLPerson.h" @implementation SLPerson static id _instance; + (instancetype)allocWithZone:(struct _NSZone *)zone { @synchronized(self){ // 必定要加互斥鎖,否則會有線程安全問題 if (_instance == nil) { _instance = [[super allocWithZone:zone] init]; } } return _instance; } + (instancetype)sharedPerson { @synchronized(self){ if (_instance == nil) { _instance = [[self alloc] init]; } } return _instance; } // 要有對象才能進行copy - (id)copyWithZone:(NSZone *)zone { return _instance; } @end