美文网首页
Block的类型和循环引用

Block的类型和循环引用

作者: Bel李玉 | 来源:发表于2020-11-12 23:23 被阅读0次

本篇文章中,我们主要来探讨iOS中的Block。

Block的类型

Block主要有三种类型分别为NSGlobalBlock、NSStackBlock、NSMallocBlock

  • 1, 当 block不捕获外界变量时,此时其类型为NSGlobalBlock
  • 2,当 局部变量block捕获外界变量,并使用weak修饰时,此时其类型为NSStackBlock
  • 3,当 局部变量block捕获外界变量,不使用weak修饰时,此时其类型为NSMallocBlock
  • 4,当全局变量block捕获外界变量时,此时其类型为NSMallocBlock
  NSObject *obj = [[NSObject alloc] init];
  void (^__weak block)(void) = ^{ // NSStackBlock
      NSLog(@"----- %@",obj);
  };
  self.block = ^(id data) { // NSGlobalBlock

  };

  self.blockTwo = ^(id data){ // NSMallocBlock
      NSLog(@"------ %@", obj);
  };
 <__NSStackBlock__: 0x7ffeee612430>
 <__NSGlobalBlock__: 0x1015ec100>
 <__NSMallocBlock__: 0x600001d6bf90>

循环引用

当使用block的时候,我们要注意循环引用的问题,防止内存泄漏,我们来看如下代码

#import "ViewController.h"

typedef void(^LYBlock)(void);
@interface ViewController ()
@property (nonatomic, copy) LYBlock block;
@property (nonatomic, copy) NSString *name;
@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    // 循环引用
    self.name = @"LY";
    self.block = ^(){
        dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
            NSLog(@"%@",self.name);
        });
    };
    self.block();
}
- (void)dealloc{
    NSLog(@"dealloc");
}

这样就产生了循环引用的问题,该ViewController不会被释放,dealloc不会调用。

为什么会产生循环引用?

在这里self引用blockblock 引用self即: self -> block ->self,导致其无法释放。

weak-strong dance

为了解决循环引用问题,我们可以使用__weak来修饰self,我们来看如下代码

- (void)viewDidLoad {
    [super viewDidLoad];
    // 循环引用
    self.name = @"LY";
    __weak typeof(self) weakSelf = self;
    self.block = ^(){
        dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
            NSLog(@"%@",weakSelf.name);
        });
    };
    self.block();
}
- (void)dealloc{
    NSLog(@"dealloc");
}

我们来看其运行结果

[24666:835170] dealloc
[24666:835170] (null)

我们可以看出,__weak解决了循环引用的问题,在异步函数执行之前,ViewController已经销毁,导致运行结果出错。此时,我们需要使用__strong来修饰weak对象。

- (void)viewDidLoad {
    [super viewDidLoad];
    // 循环引用
    self.name = @"LY";
    __weak typeof(self) weakSelf = self;
    self.block = ^(){
        __strong typeof(self) strongSelf = weakSelf;
        dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
            NSLog(@"%@",strongSelf.name);
        });
    };
    self.block();
}
- (void)dealloc{
    NSLog(@"dealloc");
}

我们来看运行结果:

[24814:841306] LY
[24814:841306] dealloc

这样运行结果就正常了。

中介者模式

下面我们将使用中介者模式进行手动解决循环引用问题。

- (void)viewDidLoad {
    [super viewDidLoad];
    // 循环引用
    self.name = @"LY";
    __block ViewController *vc = self;
    self.block = ^(){
        dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
            NSLog(@"%@",vc.name);
            vc = nil;
        });
    };
    self.block();
}
- (void)dealloc{
    NSLog(@"dealloc");
}

我们来看下运行结果:

[24958:848357] LY
[24958:848357] dealloc

在这里,我们使用了中间变量vc,这样引用关系就变成了self -> block -> vc -> block,在异步函数执行完,我们将中间变量 vc 置为nil,这样就避免了selfblock循环引用

相关文章

  • Block的类型和循环引用

    本篇文章中,我们主要来探讨iOS中的Block。 Block的类型 Block主要有三种类型分别为NSGlobal...

  • Block 深入浅出

    标签:block block的类型 循环引用的解决方法 block底层的分析 本章节主要介绍 1.block的类型...

  • 28.iOS底层学习之block初学习

    本章提纲1、Block的几种类型2、Block常见试题3、Block的循环引用问题 1、Block的几种类型 Bl...

  • NSTimer循环引用原理及解决方案

    NSTimer的循环引用和Block循环引用有什么区别? 对于block型的循环引用,我们可以通过weakSelf...

  • Block循环引用的四种解决方案

    Block常见的循环引用模型 以下是常见的Block循环引用模型,self引用block,block引用self,...

  • block分析

    本文主要介绍block的类型、循环引用的解决方法以及block底层的分析 block 类型 block主要有三种类...

  • iOS-底层原理:Block

    这里主要介绍block的类型、循环引用的解决方法以及block底层的分析 block 类型 block主要有三种类...

  • iOS Block底层原理

    本文主要介绍block的类型、循环引用的解决方法以及block底层的分析 block 类型 block主要有三种类...

  • __block与__weak的真正区别

    block下循环引用的问题 __block本身并不能避免循环引用,避免循环引用需要在block内部把__block...

  • __block和__weak修饰符的区别

    block下循环引用的问题 __block本身并不能避免循环引用,避免循环引用需要在block内部把__block...

网友评论

      本文标题:Block的类型和循环引用

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