做用:能夠保證在程序運行過程,一個類只有一個實例,並且該實例易於外界訪問atom
#import "MusicTool.h" @interface HMMusicTool () @property (strong, nonatomic) NSMutableArray *music; //.h @end @implementation MusicTool -(NSArray *)music { if (_music == nil) { _music = [NSMutableArray array]; } return _music; } static id _musicTool; + (id)allocWithZone:(struct _NSZone *)zone { if (_musicTool == nil){ //避免屢次加鎖 @synchronized(self) { //加鎖,避免屢次加載 if (_musicTool == nil) { // 防止建立屢次 _musicTool = [super allocWithZone:zone]; } } } return _musicTool; } +(instancetype)shareMusiclTool { if (_musicTool == nil){ //避免屢次加鎖 @synchronized(self){ if (_musicTool == nil) { _musicTool = [[self alloc] init]; } } } return _musicTool; } - (id)copyWithZone:(NSZone *)zone { return _musicTool; } #import "ViewController.h" @interface ViewController () @end @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; MusicTool *tool = [[MusicTool alloc] init]; MusicTool *tool1 = [[MusicTool alloc] init]; MusicTool *tool2 = [MusicTool shareMusiclTool]; MusicTool *tool3 = [tool1 copy]; NSLog(@"%p %p %p %p",tool.music,tool1.music,tool2.music,tool3.music); //返回的結果都是相同的指針,全部只有一個實例 }
/** * 當類加載到OC運行環境中(內存),就會調用一次 */ + (void)load { _moiveTool = [[self alloc] init]; } /** * 當第一次使用這個類的時候纔會調用 */ + (void)initialize { NSLog(@"-------initialize"); } + (instancetype)allocWithZone:(struct _NSZone *)zone { /** * load當即調用alloc,因此不須要加鎖 */ if (_moiveTool == nil) {//防止頻繁alloc return [super allocWithZone:zone]; } return _moiveTool; } + (instancetype)shareMoiveTool { return _moiveTool; } - (id)copyWithZone:(NSZone *)zone { return _moiveTool; }
#import "SingTool.h" @implementation SingTool //用來保存惟一的單例對象 static id _instance; +(instancetype)allocWithZone:(struct _NSZone *)zone { static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ _instance = [super allocWithZone:zone]; }); return _instance; } +(instancetype)shareSingTool { static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ _instance = [[self alloc] init]; }); return _instance; } //copy多是已存在_instance,因此直接返回 -(id)copyWithZone:(NSZone *)zone { return _instance; }
#import "SingTool.h" @implementation SingTool //用來保存惟一的單例對象 static id _instance; +(instancetype)allocWithZone:(struct _NSZone *)zone { static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ _instance = [super allocWithZone:zone]; }); return _instance; } +(instancetype)shareSingTool { static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ _instance = [[self alloc] init]; }); return _instance; } //copy多是已存在_instance,因此直接返回 -(id)copyWithZone:(NSZone *)zone { return _instance; } //重寫release,retain,retainCount,autorelease方法 //重寫release,執行release時候不進行操做 -(oneway void)release { } - (instancetype)retain { return self; } -(NSUInteger)retainCount { return 1; } -(instancetype)autorelease { return self; }
1,直接用宏定義文件,無需額外本身寫 //GCD //.h文件 #define SingletionH(name) +(instancetype)share##name; //.m文件 #if __has_feature(objc_arc) #define SingletionM(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 \ { \ static dispatch_once_t onceToken; \ dispatch_once(&onceToken, ^{ \ _instance = [[self alloc] init]; \ }); \ return _instance; \ } \ \ -(id)copyWithZone:(NSZone *)zone \ { \ return _instance; \ } #else #define SingletionM(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 \ { \ static dispatch_once_t onceToken; \ dispatch_once(&onceToken, ^{ \ _instance = [[self alloc] init]; \ }); \ return _instance; \ } \ \ -(id)copyWithZone:(NSZone *)zone \ { \ return _instance; \ } \ -(oneway void)release \ { \ \ } \ - (instancetype)retain \ { \ return self; \ } \ -(NSUInteger)retainCount \ { \ return 1; \ } \ -(instancetype)autorelease \ { \ return self; \ } #endif
#if __has_feature(objc_arc) //編譯器是ARC環境 NSLog(@"ARC環境"); #else //編譯器是MRC環境 NSLog(@"MRC環境"); #endif }