Block怎么用,是否产生循环引用。

接手过不少项目很多block要么乱用,要么就烂用。

block 产生循环引用终归都是相互持有。相信大多人都能明白,但用着用着就糊涂了。不知道是不是会产生。

下面写了个测试代码希望能帮到有需要的人。代码不多,然望看完。

有圈就是环,没圈就不成环,不释放不一定就是环所至,可能是生命周期。

//
//  AFBlockDesigned.h
//  AFBlockCylce
//
//  Created by fengsh on 2019/1/28.
//  Copyright © 2019年 fengsh. All rights reserved.
//

#import <Foundation/Foundation.h>

typedef void(^PersistentBlock) (NSString *msg);

NS_ASSUME_NONNULL_BEGIN

@interface AFBlockDesigned : NSObject

@property (nonatomic, copy) PersistentBlock             strongBlock;

///非单例
+ (instancetype)manager;

///单例
+ (instancetype)share;

///会产生循环引用的block
- (void)reqeustForPersistentBlock:(PersistentBlock)block;

///使劲用,不产生,我就不产生。
- (void)reqeustForWeakBlock:(PersistentBlock)block;

@end

NS_ASSUME_NONNULL_END
//
//  AFBlockDesigned.m
//  AFBlockCylce
//
//  Created by fengsh on 2019/1/28.
//  Copyright © 2019年 fengsh. All rights reserved.
//

#import "AFBlockDesigned.h"

@implementation AFBlockDesigned

- (void)dealloc
{
    NSLog(@"AFBlockDesigned Free.");
}

+ (instancetype)manager
{
    return [[[self class] alloc]init];
}

+ (instancetype)share
{
    static AFBlockDesigned *instance = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        instance = [[AFBlockDesigned alloc]init];
    });
    return instance;
}

///会产生循环引用的block
- (void)reqeustForPersistentBlock:(PersistentBlock)block
{
    ///全局 hold它
    self.strongBlock = block;
    
    dispatch_queue_t queue = dispatch_queue_create("com.fsh.pb", 0);
    
    dispatch_async(queue, ^{
        [NSThread sleepForTimeInterval:5];
        block(@"【reqeustForPersistentBlock:】");
    });
    
}

///使劲用,不产生,我就不产生。
- (void)reqeustForWeakBlock:(PersistentBlock)block
{
    dispatch_queue_t queue = dispatch_queue_create("com.fsh.pb", 0);
    
    dispatch_async(queue, ^{
        [NSThread sleepForTimeInterval:5];
        block(@"【reqeustForWeakBlock:】");
    });
}

@end

下面上测试代码:

//
//  GreenViewController.m
//  AFBlockCylce
//
//  Created by fengsh on 2019/1/28.
//  Copyright © 2019年 fengsh. All rights reserved.
//

#import "GreenViewController.h"
#import "AFBlockDesigned.h"

@interface GreenViewController ()
@property (nonatomic, strong) AFBlockDesigned               *manager;
@property (nonatomic, strong) NSMutableArray                *all;

@property (nonatomic, strong) AFBlockDesigned               *shareGloble;
@end

@implementation GreenViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view.
    
    self.all = [NSMutableArray array];
    
//    [self testCycleRef]; ///产生循环引用
    
//    [self testWeakFree]; ///局部持有block, 没有循环引用

//    [self testWeakRef];  ///使用弱引用,没有循环引用
    
//    [self testSingle];   ///单例情况,不持有,只是引用计数释放的生命周期而已,并非循环引用.
    
//    [self testSingleLocalBlock];///单例情况,不持有,生命周期到了就free.并非循环引用.
    
//    [self testSingleGloble];  ///产生循环引用

    [self testSingleGlobleLocalBlock]; ///不产生循环引用
}

/*
   会产生循环引用
   self(GreenViewController)---------->持有self.manager()----------->持有block
           ^                                                          |
           |___________________________持有____________________________|
 */
- (void)testCycleRef
{
    self.manager = [AFBlockDesigned manager];
    
    PersistentBlock block = ^(NSString * msg) {
        [self.all addObject:msg];
        NSLog(@"%@ ,self.manager,self,block相互持有,形成强环了。",msg);
    };
    
    NSLog(@"self地址:%p , self.manager地址:%p, block地址:%p",&self,&_manager,&block);
    NSLog(@"self地址:%p , self.manager地址:%p, block地址:%p",self,_manager,block);
    
    [self.manager reqeustForPersistentBlock:block];
    
//    [self.manager reqeustForPersistentBlock:^(NSString * msg) {
//        [self.all addObject:msg];
//        NSLog(@"%@ ,self.manager,self,block相互持有,形成强环了。",msg);
//    }];
    NSLog(@"%s ---end---",__FUNCTION__);
}

/*
 不会产生循环引用
 self(GreenViewController)-----持有----->self.manager()-----不持有----->block
            ^                                                          |
            |___________________________持有____________________________|
 */
- (void)testWeakFree
{
    self.manager = [AFBlockDesigned manager];
    
    [self.manager reqeustForWeakBlock:^(NSString * msg) {
        [self.all addObject:msg];
        NSLog(@"%@ ,block只作入参,不持有block",msg);
    }];
    NSLog(@"%s ---end---",__FUNCTION__);
}

/*
 不会产生循环引用
 self(GreenViewController)----持有------>self.manager()-----持有----->block
            ^                                                          |
            |.......................weak持有............................|
 */
- (void)testWeakRef
{
    self.manager = [AFBlockDesigned manager];
    __weak typeof(self) ws = self;
    [self.manager reqeustForPersistentBlock:^(NSString * msg) {
        __strong typeof(self) ss = ws;
        [ss.all addObject:msg];
        NSLog(@"%@ 使用了__weak进行修饰,打破强引用!",msg);
    }];
    NSLog(@"%s ---end---",__FUNCTION__);
}

/*
 单例模式:不会产生循环引用,但由于引用计数不为0,故没有释放,并不是循环引用
 self(GreenViewController)-----不持有----->单例-----------持有---------->block
        ^                                                               |
        |___________________________持有_________________________________|
 */
- (void)testSingle
{
    [[AFBlockDesigned share]reqeustForPersistentBlock:^(NSString *msg) {
         [self.all addObject:msg];
        NSLog(@"单例 %@,并不持有,因此没成环!,但为啥不释放啊,因为这是个全局单例,在这里引用计数被+1了.",msg);
//        [AFBlockDesigned share].strongBlock = nil;加这一句就是释放block从而使self的引用计数-1
    }];
    NSLog(@"%s ---end---",__FUNCTION__);
}

/*
 单例模式:不会产生循环引用,但由于引用计数不为0,故没有释放,并不是循环引用
 self(GreenViewController)-----不持有----->单例-----------不持有---------->block
        ^                                                                |
        |____________________________持有_________________________________|
 */
- (void)testSingleLocalBlock
{
    [[AFBlockDesigned share]reqeustForWeakBlock:^(NSString *msg) {
        [self.all addObject:msg];
        NSLog(@"%@ self不持有,单例不持有block,没有形成环,函数执行完成后block也随之被free.所以对self的引用计数也减1",msg);
    }];
    NSLog(@"%s ---end---",__FUNCTION__);
}

/*
 单例模式:产生循环引用
 self(GreenViewController)-----持有----->单例-----------持有---------->block
    ^                                                                |
    |____________________________持有_________________________________|
 */

- (void)testSingleGloble
{
    self.shareGloble = [AFBlockDesigned share];
    [self.shareGloble reqeustForPersistentBlock:^(NSString *msg) {
         [self.all addObject:msg];
        NSLog(@"%@ 单例并且持有了! 会有循环引用问题",msg);
    }];
    NSLog(@"%s ---end---",__FUNCTION__);
}

/*
 单例模式:不会产生循环引用
 self(GreenViewController)-----持有----->单例----------不持有--------->block
    ^                                                                |
    |____________________________持有_________________________________|
 */
- (void)testSingleGlobleLocalBlock
{
    self.shareGloble = [AFBlockDesigned share];
    [self.shareGloble reqeustForWeakBlock:^(NSString *msg) {
        [self.all addObject:msg];
        NSLog(@"%@ 持有单例,但不持有block",msg);
    }];
    
    NSLog(@"%s ---end---",__FUNCTION__);
}

- (void)dealloc
{
    NSLog(@"GreenViewController Free.");
}

@end

最后上两个clang  转C代码,有兴趣的可以看下转C后的结构,从底往上看。都是struct不麻烦的。

方式一:clang -x objective-c -rewrite-objc -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator.sdk AFBlockDesigned.m

注意这里还有些可能存在依赖问题,要针对性加参数处理。

方式二:

xcrun -sdk iphonesimulator clang -rewrite-objc -fobjc-arc -fblocks -fobjc-runtime=ios-12.1 GreenViewController.m

DEMO:上传完成再来修改地址。CSDN强行设置5分太恶心了。要吐。不能设0么?

猜你喜欢

转载自blog.csdn.net/fengsh998/article/details/86681052