单例实现代码(懒汉式)
.h文件
1 #import <Foundation/Foundation.h> 2 3 @interface MusicLab : NSObject 4 5 //封装类方法 6 +(instancetype)shareMusicLab; 7 8 @end
.m文件
1 #import "MusicLab.h" 2 3 @interface MusicLab() 4 5 //类延展中创建的实例变量和属性,都不能被其他类中创建的该类对象访问,必须放在.h文件中 6 7 @end 8 9 @implementation MusicLab 10 11 12 //搞个全局变量来保存MusicLab类创建的唯一对象. 必须加static,否则别的.m文件可以修改它 13 static MusicLab *musicObj; 14 15 16 //此方法也判断两次,为了防止某个SB不使用单例shareMusicLab方法,直接调用[[MusicLab alloc]init]; 17 //类调用alloc方法,其实是在调用allocWithZone方法 18 +(instancetype)allocWithZone:(struct _NSZone *)zone{ 19 20 if (musicObj == nil) { //此判定是为了每次调用alloc方法时都要加锁 21 @synchronized(self){ 22 NSLog(@"已经加锁"); 23 if (!musicObj) { //防止多个线程进来判定musicObj=nil,在此之前加锁,进不来。 24 musicObj = [super allocWithZone:zone]; //该代码执行完,musicObj就不在是空nil了, 25 } 26 } 27 28 } 29 30 return musicObj; 31 } 32 33 34 +(instancetype)shareMusicLab{ 35 36 //假设2个线程A.B同时进来,判定musicObj的确是nil, 37 if(musicObj == nil){ //线程A,B来到这里,但是此线程加锁。假设A加锁后进入,B在外面等待 38 39 @synchronized(self){//线程A加锁后进入 40 41 if (musicObj == nil) {//线程A判定为空,继续执行 42 43 musicObj = [[self alloc]init];//线程A创建musicObj对象 44 } 45 }//线程A出门,musicObj已经有值了。线程B继续上锁进入,但是此时if (musicObj == nil)不成立,只得返回 46 } 47 48 return musicObj; 49 50 } 51 52 -(id)copyWithZone:(NSZone *)zone{ 53 54 return musicObj; 55 } 56 57 58 59 //NSLog遇到%@就会调用该方法,将该方法返回的字符串替代%@后面的值。 60 //- (NSString *)description{ 61 // return [NSString stringWithFormat:@"地址:%p",self]; 62 //} 63 64 @end
ViewController.m文件
1 //单例: 确保一个类无论调用它多少次,用它创建多少个对象,其创建的都是同一个对象,这些对象调用它内部的属性,得到的都是相同的值 2 3 #import "ViewController.h" 4 #import "MusicLab.h" 5 6 @interface ViewController () 7 8 @end 9 10 @implementation ViewController 11 12 - (void)viewDidLoad { 13 [super viewDidLoad]; 14 15 //因为每次创建对象都要调用alloc分配内存,故单例需从alloc方法下手,调用alloc方法,其本质又是调用 16 MusicLab *musicLab = [[MusicLab alloc]init]; 17 MusicLab *musicLab1 = [[MusicLab alloc]init]; 18 MusicLab *musicLab2 = [[MusicLab alloc]init]; //修改代码后只有第一次加锁,后面调用都不加锁,故加锁方法只被打印一次 19 MusicLab *musicLab3 = [MusicLab shareMusicLab]; 20 MusicLab *musicLab4 = [musicLab2 copy]; //copy方法会调用copyWithZone; 21 22 NSLog(@" musicLab地址: %p musicLab1地址:%p",musicLab,musicLab1); 23 NSLog(@" musicLab3地址:%p musicLab4地址:%p",musicLab3,musicLab4); 24 25 // NSLog(@" musicLab实例变量地址: %p musicLab1实例变量地址:%p",musicLab.musics,musicLab1.musics); //同一个类的不同对象调用musics属性返回相同的地址,单例已实现 26 27 }