美文网首页
GCD--dispatch_once_t

GCD--dispatch_once_t

作者: 初灬终 | 来源:发表于2018-12-02 07:56 被阅读7次
/*!
 * @function dispatch_once
 *
 * @abstract
 * Execute a block once and only once.
 *
 * @param predicate
 * A pointer to a dispatch_once_t that is used to test whether the block has
 * completed or not.
 *
 * @param block
 * The block to execute once.
 *
 * @discussion
 * Always call dispatch_once() before using or testing any variables that are
 * initialized by the block.
 */
typedef long dispatch_once_t;
void
dispatch_once(dispatch_once_t *predicate,
        DISPATCH_NOESCAPE dispatch_block_t block);

场景:项目中唯一的,且需要全局访问的对象,我们使用单例。

#import <Foundation/Foundation.h>

@interface User : NSObject
@property (nonatomic, strong) NSString *job;
+ (User *)sharedInstance;
@end
#import "User.h"

static dispatch_once_t user_onceToken;
@implementation User
+ (User *)sharedInstance {
    static User *user = nil;
    dispatch_once(&user_onceToken, ^{
        user = [[User alloc]init];
    });
    return user;
}
@end
[User sharedInstance].job = @"iOS developer";
NSLog(@"%@====%@",[User sharedInstance],[User sharedInstance].job);//<User: 0x600000018450>====iOS developer

场景:项目中,在退出时,需要把单例数据清空,该怎么做 ??

先简单的把单例对象设置 user = nil; 然而根本没用。
单例的数据实际上是 static User *user 这个静态变量保存着。
方案一:直接把单例的所有属性一一清空数据。
方案二:单例重新初始化,通过代码控制dispatch_once的block。(我以前一直误以为是不是dispatch_once_t *predicate,这个指针初始为空,执行一次后非空,这样子控制block是否执行。)

#import "User.h"

static dispatch_once_t user_onceToken;
@implementation User
+ (User *)sharedInstance {
    static User *user = nil;
    NSLog(@"before: %ld--%p",user_onceToken, &user_onceToken);
    dispatch_once(&user_onceToken, ^{
        NSLog(@"after: %ld--%p",user_onceToken, &user_onceToken);
        user = [[User alloc]init];
    });
    return user;
}
@end

调用单例的代码

 [User sharedInstance].job = @"iOS developer";
 NSLog(@"%@====%@",[User sharedInstance],[User sharedInstance].job);

输出结果

2018-12-02 07:37:09.284862+0800 dispatch_once_t-Demo[51477:2436486] before: 0--0x1001100f8
2018-12-02 07:37:09.285004+0800 dispatch_once_t-Demo[51477:2436486] after: 768--0x1001100f8
2018-12-02 07:37:09.285141+0800 dispatch_once_t-Demo[51477:2436486] before: -1--0x1001100f8
2018-12-02 07:37:09.285246+0800 dispatch_once_t-Demo[51477:2436486] before: -1--0x1001100f8

发现:
第一次[User sharedInstance],static dispatch_once_t user_onceToken 初始值为0。
然后进入了block,static dispatch_once_t user_onceToken 变成了768。
第二次调用[User sharedInstance],static dispatch_once_t user_onceToken 初始值为-1,没有进入block。
第三次调用[User sharedInstance],static dispatch_once_t user_onceToken 初始值为-1,没有进入block。
而且从头到位静态变量指针没有发生变化。
猜想:是不是修改static dispatch_once_t user_onceToken;这个静态变量的值,就可以控制block是否执行。

#import <Foundation/Foundation.h>

@interface User : NSObject
@property (nonatomic, strong) NSString *job;
+ (User *)sharedInstance;
- (void)deleteUser;
@end
static dispatch_once_t user_onceToken;
@implementation User
+ (User *)sharedInstance {
    static User *user = nil;
    NSLog(@"before: %ld--%p",user_onceToken, &user_onceToken);
    dispatch_once(&user_onceToken, ^{
        NSLog(@"after: %ld--%p",user_onceToken, &user_onceToken);
        user = [[User alloc]init];
    });
    return user;
}

- (void)deleteUser {
    user_onceToken = 0;
}
@end

调用单例

    [User sharedInstance].job = @"iOS developer";
    NSLog(@"%@====%@",[User sharedInstance],[User sharedInstance].job);

    [[User sharedInstance] deleteUser];
    NSLog(@"%@====%@",[User sharedInstance],[User sharedInstance].job);

输出结果

2018-12-02 07:50:46.558717+0800 dispatch_once_t-Demo[51640:2456936] before: 0--0x10e847100
2018-12-02 07:50:46.558891+0800 dispatch_once_t-Demo[51640:2456936] after: 768--0x10e847100
2018-12-02 07:50:46.559008+0800 dispatch_once_t-Demo[51640:2456936] before: -1--0x10e847100
2018-12-02 07:50:46.559091+0800 dispatch_once_t-Demo[51640:2456936] before: -1--0x10e847100
2018-12-02 07:50:46.559624+0800 dispatch_once_t-Demo[51640:2456936] <User: 0x600000012530>====iOS developer
2018-12-02 07:50:46.560110+0800 dispatch_once_t-Demo[51640:2456936] before: -1--0x10e847100
2018-12-02 07:50:46.560254+0800 dispatch_once_t-Demo[51640:2456936] before: 0--0x10e847100 //改为0
2018-12-02 07:50:46.560501+0800 dispatch_once_t-Demo[51640:2456936] after: 768--0x10e847100
2018-12-02 07:50:46.560983+0800 dispatch_once_t-Demo[51640:2456936] before: -1--0x10e847100
2018-12-02 07:50:46.561175+0800 dispatch_once_t-Demo[51640:2456936] <User: 0x604000007f00>====(null)

大功告成,只需要把dispatch_once_t user_onceToken改成0,就重新初始化User了。

相关文章

  • GCD--dispatch_once_t

    场景:项目中唯一的,且需要全局访问的对象,我们使用单例。 场景:项目中,在退出时,需要把单例数据清空,该怎么做 ?...

网友评论

      本文标题:GCD--dispatch_once_t

      本文链接:https://www.haomeiwen.com/subject/reydcqtx.html