区块链技术博客
www.b2bchain.cn

iOS面试题目解析21 – Block的循环引用求职学习资料

本文介绍了iOS面试题目解析21 – Block的循环引用求职学习资料,有助于帮助完成毕业设计以及求职,是一篇很好的资料。

对技术面试,学习经验等有一些体会,在此分享。

Block循环引用

当Block从栈复制到堆上时,Block会持有捕获的对象,这样就容易产生循环引用。比如在self中引用了Block,Block优捕获了self,就会引起循环引用,编译器通常能检测出这种循环引用:

@interface TestObject : NSObject @property(nonatomic, copy) void (^blk)(void); @end  @implementation TestObject - (instancetype)init {     self = [super init];     if (self) {         self.blk = ^{             NSLog(@"%@", self); // warning:Capturing 'self' strongly in this block is likely to lead to a retain cycle         };     }     return self; }

如果捕获到的是当前对象的成员变量对象,同样也会造成对self的引用,比如下面的代码,Block使用了self对象的的成员变量name,实际上就是捕获了self,对于编译器来说name只不过时对象用结构体的成员变量:

@interface TestObject : NSObject @property(nonatomic, copy) void (^blk)(void); @property(nonatomic, copy) NSString *name; @end  @implementation TestObject - (instancetype)init {     self = [super init];     if (self) {         self.blk = ^{             NSLog(@"%@", self.name);         };     }     return self; } @end

解决循环引用的方法有两种:

1.使用__weak来声明self:使用 __weak 修饰符修饰对象之后,在Block中对对象就是弱引用:

- (instancetype)init {     self = [super init];     if (self) {         __weak typeof(self) weakSelf = self;         self.blk = ^{             NSLog(@"%@", weakSelf.name);         };     }     return self; }

2.使用临时变量来避免引用self

- (instancetype)init {     self = [super init];     if (self) {         id tmp = self.name;         self.blk = ^{             NSLog(@"%@", tmp);         };     }     return self; }

循环引用相关题目

1.下面的代码存在循环引用吗?如果有如何解决?

#import <Foundation/Foundation.h>  typedef void(^Study)(); @interface Student : NSObject @property (copy , nonatomic) NSString *name; @property (copy , nonatomic) Study study;  @end  #import "ViewController.h" #import "Student.h"  @interface ViewController () @end  @implementation ViewController  - (void)viewDidLoad {      [super viewDidLoad];       Student *student = [[Student alloc]init];      student.name = @"Jack";       student.study = ^{          NSLog(@"my name is = %@", student.name);      }; } @end
  • 答案:存在循环引用。

  • 原因:student 的 study 的 Block 里面通过student.name 强引用了 student 自身。MallocBlock捕获了外部的对象 student,会在内部持有它。引用计数的值会增加1。

  • 解决办法:

    • 方法1:直接对 student 使用 __block ,并将内部的 student 设置为 nil ,不会打破循环引用:
    #import "ViewController.h" #import "Student.h"  @interface ViewController () @end  @implementation ViewController  - (void)viewDidLoad {     [super viewDidLoad];
    Student *student = [[Student alloc]init];  __block Student *stu = student; student.name = @"Jack"; student.study = ^{     NSLog(@"my name is = %@", stu.name);     stu = nil; };

    }

    原因:由于没有执行 study 这个 block,现在 student 持有该 block,block 持有 __block 变量,__block 变量又持有 student 对象。3者形成了环,导致了循环引用了。

    • 方法2: 对 student 使用 __block,并执行 block,破坏掉其中一个引用
    #import "ViewController.h" #import "Student.h"  @interface ViewController () @end  @implementation ViewController  - (void)viewDidLoad {     [super viewDidLoad];
    Student *student = [[Student alloc]init];  __block Student *stu = student; student.name = @"Jack"; student.study = ^{     NSLog(@"my name is = %@", stu.name);     stu = nil; };  // 执行这个 block student.study();

    }

    • 方法3: 使用 __weak ,对 student 使用 __weak,则 block 就不会强引用 student
      “`objc

    import “ViewController.h”

    import “Student.h”

    @interface ViewController ()
    @end

    @implementation ViewController

    • (void)viewDidLoad {
      [super viewDidLoad];

      Student *student = [[Student alloc]init];
      student.name = @”Jack”;

      __weak typeof(student) weakStu = student;

      student.study = ^{
      NSLog(@”my name is = %@”, weakStu.name);

Block循环引用

当Block从栈复制到堆上时,Block会持有捕获的对象,这样就容易产生循环引用。比如在self中引用了Block,Block优捕获了self,就会引起循环引用,编译器通常能检测出这种循环引用:

@interface TestObject : NSObject @property(nonatomic, copy) void (^blk)(void); @end  @implementation TestObject - (instancetype)init {     self = [super init];     if (self) {         self.blk = ^{             NSLog(@"%@", self); // warning:Capturing 'self' strongly in this block is likely to lead to a retain cycle         };     }     return self; }

如果捕获到的是当前对象的成员变量对象,同样也会造成对self的引用,比如下面的代码,Block使用了self对象的的成员变量name,实际上就是捕获了self,对于编译器来说name只不过时对象用结构体的成员变量:

@interface TestObject : NSObject @property(nonatomic, copy) void (^blk)(void); @property(nonatomic, copy) NSString *name; @end  @implementation TestObject - (instancetype)init {     self = [super init];     if (self) {         self.blk = ^{             NSLog(@"%@", self.name);         };     }     return self; } @end

解决循环引用的方法有两种:

1.使用__weak来声明self:使用 __weak 修饰符修饰对象之后,在Block中对对象就是弱引用:

- (instancetype)init {     self = [super init];     if (self) {         __weak typeof(self) weakSelf = self;         self.blk = ^{             NSLog(@"%@", weakSelf.name);         };     }     return self; }

2.使用临时变量来避免引用self

- (instancetype)init {     self = [super init];     if (self) {         id tmp = self.name;         self.blk = ^{             NSLog(@"%@", tmp);         };     }     return self; }

循环引用相关题目

1.下面的代码存在循环引用吗?如果有如何解决?

#import <Foundation/Foundation.h>  typedef void(^Study)(); @interface Student : NSObject @property (copy , nonatomic) NSString *name; @property (copy , nonatomic) Study study;  @end  #import "ViewController.h" #import "Student.h"  @interface ViewController () @end  @implementation ViewController  - (void)viewDidLoad {      [super viewDidLoad];       Student *student = [[Student alloc]init];      student.name = @"Jack";       student.study = ^{          NSLog(@"my name is = %@", student.name);      }; } @end
  • 答案:存在循环引用。

  • 原因:student 的 study 的 Block 里面通过student.name 强引用了 student 自身。MallocBlock捕获了外部的对象 student,会在内部持有它。引用计数的值会增加1。

  • 解决办法:

    • 方法1:直接对 student 使用 __block ,并将内部的 student 设置为 nil ,不会打破循环引用:
    #import "ViewController.h" #import "Student.h"  @interface ViewController () @end  @implementation ViewController  - (void)viewDidLoad {     [super viewDidLoad];
    Student *student = [[Student alloc]init];  __block Student *stu = student; student.name = @"Jack"; student.study = ^{     NSLog(@"my name is = %@", stu.name);     stu = nil; };

    }

    原因:由于没有执行 study 这个 block,现在 student 持有该 block,block 持有 __block 变量,__block 变量又持有 student 对象。3者形成了环,导致了循环引用了。

    • 方法2: 对 student 使用 __block,并执行 block,破坏掉其中一个引用
    #import "ViewController.h" #import "Student.h"  @interface ViewController () @end  @implementation ViewController  - (void)viewDidLoad {     [super viewDidLoad];
    Student *student = [[Student alloc]init];  __block Student *stu = student; student.name = @"Jack"; student.study = ^{     NSLog(@"my name is = %@", stu.name);     stu = nil; };  // 执行这个 block student.study();

    }

    • 方法3: 使用 __weak ,对 student 使用 __weak,则 block 就不会强引用 student
      “`objc

    import “ViewController.h”

    import “Student.h”

    @interface ViewController ()
    @end

    @implementation ViewController

    • (void)viewDidLoad {
      [super viewDidLoad];

      Student *student = [[Student alloc]init];
      student.name = @”Jack”;

      __weak typeof(student) weakStu = student;

      student.study = ^{
      NSLog(@”my name is = %@”, weakStu.name);

Block循环引用

当Block从栈复制到堆上时,Block会持有捕获的对象,这样就容易产生循环引用。比如在self中引用了Block,Block优捕获了self,就会引起循环引用,编译器通常能检测出这种循环引用:

@interface TestObject : NSObject @property(nonatomic, copy) void (^blk)(void); @end  @implementation TestObject - (instancetype)init {     self = [super init];     if (self) {         self.blk = ^{             NSLog(@"%@", self); // warning:Capturing 'self' strongly in this block is likely to lead to a retain cycle         };     }     return self; }

如果捕获到的是当前对象的成员变量对象,同样也会造成对self的引用,比如下面的代码,Block使用了self对象的的成员变量name,实际上就是捕获了self,对于编译器来说name只不过时对象用结构体的成员变量:

@interface TestObject : NSObject @property(nonatomic, copy) void (^blk)(void); @property(nonatomic, copy) NSString *name; @end  @implementation TestObject - (instancetype)init {     self = [super init];     if (self) {         self.blk = ^{             NSLog(@"%@", self.name);         };     }     return self; } @end

解决循环引用的方法有两种:

1.使用__weak来声明self:使用 __weak 修饰符修饰对象之后,在Block中对对象就是弱引用:

- (instancetype)init {     self = [super init];     if (self) {         __weak typeof(self) weakSelf = self;         self.blk = ^{             NSLog(@"%@", weakSelf.name);         };     }     return self; }

2.使用临时变量来避免引用self

- (instancetype)init {     self = [super init];     if (self) {         id tmp = self.name;         self.blk = ^{             NSLog(@"%@", tmp);         };     }     return self; }

循环引用相关题目

1.下面的代码存在循环引用吗?如果有如何解决?

#import <Foundation/Foundation.h>  typedef void(^Study)(); @interface Student : NSObject @property (copy , nonatomic) NSString *name; @property (copy , nonatomic) Study study;  @end  #import "ViewController.h" #import "Student.h"  @interface ViewController () @end  @implementation ViewController  - (void)viewDidLoad {      [super viewDidLoad];       Student *student = [[Student alloc]init];      student.name = @"Jack";       student.study = ^{          NSLog(@"my name is = %@", student.name);      }; } @end
  • 答案:存在循环引用。

  • 原因:student 的 study 的 Block 里面通过student.name 强引用了 student 自身。MallocBlock捕获了外部的对象 student,会在内部持有它。引用计数的值会增加1。

  • 解决办法:

    • 方法1:直接对 student 使用 __block ,并将内部的 student 设置为 nil ,不会打破循环引用:
    #import "ViewController.h" #import "Student.h"  @interface ViewController () @end  @implementation ViewController  - (void)viewDidLoad {     [super viewDidLoad];
    Student *student = [[Student alloc]init];  __block Student *stu = student; student.name = @"Jack"; student.study = ^{     NSLog(@"my name is = %@", stu.name);     stu = nil; };

    }

    原因:由于没有执行 study 这个 block,现在 student 持有该 block,block 持有 __block 变量,__block 变量又持有 student 对象。3者形成了环,导致了循环引用了。

    • 方法2: 对 student 使用 __block,并执行 block,破坏掉其中一个引用
    #import "ViewController.h" #import "Student.h"  @interface ViewController () @end  @implementation ViewController  - (void)viewDidLoad {     [super viewDidLoad];
    Student *student = [[Student alloc]init];  __block Student *stu = student; student.name = @"Jack"; student.study = ^{     NSLog(@"my name is = %@", stu.name);     stu = nil; };  // 执行这个 block student.study();

    }

    • 方法3: 使用 __weak ,对 student 使用 __weak,则 block 就不会强引用 student
      “`objc

    import “ViewController.h”

    import “Student.h”

    @interface ViewController ()
    @end

    @implementation ViewController

    • (void)viewDidLoad {
      [super viewDidLoad];

      Student *student = [[Student alloc]init];
      student.name = @”Jack”;

      __weak typeof(student) weakStu = student;

      student.study = ^{
      NSLog(@”my name is = %@”, weakStu.name);

部分转自互联网,侵权删除联系

赞(0) 打赏
部分文章转自网络,侵权联系删除b2bchain区块链学习技术社区 » iOS面试题目解析21 – Block的循环引用求职学习资料
分享到: 更多 (0)

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址

b2b链

联系我们联系我们