GCD之用dispatch_once建立单例

 

        单例模式是开发者经常使用的一种设置模式,常见的实现方式为:在类中编写名为 sharedInstance的方法,该方法只会返回全类共用的单例实例,而不会在每次调用时建立新的实例.安全

        常见的作法是:函数

+ (instancetype)sharedUser {
    static User *_sharedInstance = nil;
    @synchronized(self) {
        if (!_sharedInstance) {
            _sharedInstance = [[self alloc] init];
        }
    }
    return _sharedInstance;
}

为了保证线程安全,上面的代码把建立代理的代码包裹在同步块里. spa

        相对于上面的实现方式,使用GCD的dispatch_once实现起来更为容易. 所用到的函数是:线程

     static dispatch_once_t onceToken;代理

     dispatch_once(&onceToken, ^{code

     //  code to be executed oncetoken

     });作用域

        此函数接受的类型为 dispatch_once_t的特殊函数 token,此外还接受块参数.对于给定的token来讲,该函数保证相关的块一定会执行,且仅执行一次.首次调用该函数时必然会执行块中的代码,最重要的是:次操做彻底是线程安全的!!!须要注意的是:对于只需执行一次的块来讲,每次调用函数时传入的token必须彻底相同.因此一般将token标记声明在static或者global做用域里.开发

    使用GCD实现单例方法以下:字符串

+ (instancetype)sharedUser{
    static User *_shareInstance = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        if (!_shareInstance) {
            _shareInstance = [[self alloc] init];
        }
    });
    return _shareInstance;
}

使用dispatch_once能够简化代码而且实现线程安全,所以你无需担忧加锁或者同步的问题.全部问题都有GCD在底层处理.因为每次调用时都必须使用彻底相同的token,因此token须要声明为static. 把token声明在static做用内,能够保证编译器每次执行shareUser方法时都会复用这个变量,而不会建立新的变量.

    此外,dispatch_once更高效. 他没有使用重量级的加锁机制,若是是使用加锁的话,每次运行代码前都要获取锁,相反 dispatch_once 函数采用原子访问来查询token,以判断对应的代码是否已经执行过.

    --> 使用 dispathch_once 能够轻松编写 "只需运行一次的线程安全代码",能够轻松实现单例.

    --> token 应该声明在static或者golbal做用域中,这样的话吧只需执行一次的块传给dispatch_once函数时,能够保证传进去的token也是相同的.

    附赠一份快速实现单例的 .h 文件

调用以下:

1.导入 Singleton.h文件

2.在类的.h文件中 singleton_h(单例的名字),以User类举例,单例的名字会自动拼接上 shared

#import <Foundation/Foundation.h>
#import "Singleton.h"
@interface User : NSObject

singleton_h(User);

@end

#import "User.h"

@implementation User

singleton_m(User);

@end

3.调用

User *user =  [User sharedUser];

// ## : 链接字符串和参数
#define singleton_h(name) + (instancetype)shared##name;

#if __has_feature(objc_arc) // ARC

#define singleton_m(name) \
static id _instance; \
+ (id)allocWithZone:(struct _NSZone *)zone \
{ \
    static dispatch_once_t onceToken; \
    dispatch_once(&onceToken, ^{ \
        _instance = [super allocWithZone:zone]; \
    }); \
    return _instance; \
} \
 \
+ (instancetype)shared##name \
{ \
    static dispatch_once_t onceToken; \
    dispatch_once(&onceToken, ^{ \
        _instance = [[self alloc] init]; \
    });\
    return _instance; \
} \
+ (id)copyWithZone:(struct _NSZone *)zone \
{ \
    return _instance; \
}

#else // 非ARC

#define singleton_m(name) \
static id _instance; \
+ (id)allocWithZone:(struct _NSZone *)zone \
{ \
static dispatch_once_t onceToken; \
dispatch_once(&onceToken, ^{ \
_instance = [super allocWithZone:zone]; \
}); \
return _instance; \
} \
\
+ (instancetype)shared##name \
{ \
static dispatch_once_t onceToken; \
dispatch_once(&onceToken, ^{ \
_instance = [[self alloc] init]; \
}); \
return _instance; \
} \
\
- (oneway void)release \
{ \
\
} \
\
- (id)autorelease \
{ \
return _instance; \
} \
\
- (id)retain \
{ \
return _instance; \
} \
\
- (NSUInteger)retainCount \
{ \
return 1; \
} \
\
+ (id)copyWithZone:(struct _NSZone *)zone \
{ \
return _instance; \
}

#endif

------------------

  文献参考:<编写高质量OSX和iOS代码的52个有效方法>

相关文章
相关标签/搜索