关于单例、block和dispatch_after的笔记

2021-08-09  本文已影响0人  大成小栈
  1. 单例的指针被静态存储器的静态变量引用着,单例不能释放,直到程序退出或者杀死后,内存才能被释放。那么,怎样中途释放单例呢?
  2. dispatch_after和performSelector:afterDelay:会引起强引用self,并导致循环引用吗?
  3. 在单例中强引用的block,其中的self会强引用该单例吗?

测试以下代码,可解相关疑惑:

//// .h
#import <Foundation/Foundation.h>

@interface TestInstance : NSObject

+ (instancetype)sharedInstance;
+ (void)attempDealloc;
- (void)testDisptchAfter;
- (void)test;

@end


//// .m
#import "TestInstance.h"

typedef void(^TestBlock)(NSInteger value);

@interface TestInstance ()

@property (nonatomic, copy)TestBlock testBlock;
@property (nonatomic, strong)NSString *testTitle;

@end

static TestInstance *manager = nil;
static dispatch_once_t onceToken;

@implementation TestInstance

+ (instancetype)sharedInstance {
    
    dispatch_once(&onceToken, ^{
        manager = [[TestInstance alloc] init];
        
        
    });
    return manager;
}

- (void)testDisptchAfter {
    
//    [self performSelector:@selector(haha) withObject:nil afterDelay:1.0];
    
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{

        self.testTitle =  @"testDisptchAfter";

    });
}

- (void)haha {
    
    self.testTitle =  @"haha";
}

- (void)test{
    
    __weak typeof(self)weakSelf = self;
    _testBlock = ^(NSInteger value) {
        weakSelf.testTitle = [NSString stringWithFormat:@"%d", value];
//        self.testTitle = [NSString stringWithFormat:@"%d", value];
    };
    _testBlock(5);
}

- (void)dealloc
{
    NSLog(@"dealloc------>>");
}

+ (void)attempDealloc {
//    onceToken = 0; // 只有置成0,GCD才会认为它从未执行过.它默认为0,这样才能保证下次再次调用shareInstance的时候,再次创建对象.
    manager = nil;
}

@end

答案:

  1. 只有全局的onceToken置成0,系统才能释放manager;才能保证下次再次调用shareInstance的时候,再次创建对象。
    onceToken = 0;
    manager = nil;
  2. dispatch_after和performSelector:afterDelay:不会引起强引用self。
  3. 单例中block会强引用self。但是,一般单例是不随便释放的,若不强制释放,其dealloc不管是否有block的存在,都不会走。
上一篇下一篇

猜你喜欢

热点阅读