要实现单例,关键是要保证类的alloc和init仅仅被调用一次。而且被自身强引用防止释放。
近日读唐巧先生的《iOS开发进阶》。受益匪浅,通过GCD实现单例就是收获之中的一个,以下把这种方法与大家分享。
在GCD中,有一个函数dispatch_once,能够实现代码段的一次性运行,和static修饰的变量赋值的一次性一样。我们结合static和dispatch_once,就能够简单的实现单例。
以下的代码实现了SomeClass单例:
#import <Foundation/Foundation.h>
@interface SomeClass : NSObject
+ (SomeClass *)sharedInstance;
@end
#import "SomeClass.h"
@implementation SomeClass
+ (SomeClass *)sharedInstance{
static id sharedInstance = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
sharedInstance = [[self alloc] init];
});
return sharedInstance;
}
@end
以下解释一下这段代码。
第一句新建一个sharedInstance静态强指针,是为了指向创建好的单例,防止其释放,仅仅有第一次进入的时候指针被赋值为nil。
一定注意dispatch_once_t变量必须是静态,它的值用于推断是否已经运行一次。
第二句和dispatch_once是固定使用方法,这样能够实现block内的代码一次性运行。也就是说仅仅有第一次调用这种方法时才会实例化类。之后都是返回指针指向的值。
最后返回指针,就相当于拿到了单例。
对单例的执行结果进行验证:
我们多次获取单例对象而且打印地址,能够发现地址是一样的。
#import "ViewController.h"
#import "SomeClass.h"
@interface ViewController ()
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
SomeClass *sc1 = [SomeClass sharedInstance];
SomeClass *sc2 = [SomeClass sharedInstance];
SomeClass *sc3 = [SomeClass sharedInstance];
NSLog(@"%p %p %p",sc1,sc2,sc3);
}
@end
2015-08-17 20:59:22.139 基于GCD实现单例[2785:31918] 0x7fb40af11b90 0x7fb40af11b90 0x7fb40af11b90
通过这样的方式,简单高效的实现了单例,值得使用。