博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
GCD之用dispatch_once创建单例
阅读量:6935 次
发布时间:2019-06-27

本文共 3001 字,大约阅读时间需要 10 分钟。

  hot3.png

 

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

        常见的做法是:

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

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

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

     static dispatch_once_t onceToken;

     dispatch_once(&onceToken, ^{

     //  code to be executed once

     });

        此函数接受的类型为 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 
#import "Singleton.h"@interface User : NSObjectsingleton_h(User);@end#import "User.h"@implementation Usersingleton_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个有效方法>

转载于:https://my.oschina.net/zhxx/blog/685373

你可能感兴趣的文章
Mybatis mapper文件中的转义方法
查看>>
docker inspect命令
查看>>
联合索引小结
查看>>
Linux 源码安装MariaDB 10.0.16
查看>>
mongoDB 固定集合(capped collection)
查看>>
android自定义控件(二) 入门,继承View
查看>>
看一眼就学会的 HTML 小游戏搭建!
查看>>
hdu 敌兵布阵
查看>>
git
查看>>
python添加tab键功能
查看>>
sql语句对数据库表进行加锁和解锁
查看>>
[C++] String to Int
查看>>
java面试题整理一(转灰灰+灰灰)
查看>>
【赛时总结】 ◇赛时·IV◇ CODE FESTIVAL 2017 Final
查看>>
软考倒计时21天:9大管理工具技术
查看>>
记录java中常用的英文单词01
查看>>
BeanUtil拷贝
查看>>
bootstrap精简教程
查看>>
ios UIView
查看>>
mysql 5.7 详细图文安装教程
查看>>