网络编程

当前位置:永利402游戏网站-永利402com官方网站 > 网络编程 > iOS 面试题(三)几时在 block 中无需运用 weakSel

iOS 面试题(三)几时在 block 中无需运用 weakSel

来源:http://www.xtcsyb.com 作者:永利402游戏网站-永利402com官方网站 时间:2019-09-15 16:34

**1.block 分配的地址 **block 大概可以分配到3个地方NSGlobalBlock永利402游戏网站,NSMallocBlockNSStackBlock

我们知道,在使用 block 的时候,为了避免产生循环引用,通常需要使用 weakSelf 与 strongSelf,写下面这样的代码:

**2.下面写个demo详细介绍上面的3个点 **

__weak typeof(self) weakSelf = self;
[self doSomeBackgroundJob:^{
   __strong typeof(weakSelf) strongSelf = weakSelf;
   if (strongSelf) {
       ...
   }
}];

//// ViewController.m// strong weak 的用法//// Created by apple on 16/7/5.// Copyright © 2016年 李重阳. All rights reserved.//#import "ViewController.h"@interface ViewController ()@property (nonatomic,assign) int add;@property (nonatomic,weak) void;@property (nonatomic,weak) void();@property (nonatomic,weak) void();@end@implementation ViewController- viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view, typically from a nib. self.add = 1; __weak typeof weakSelf = self; /*-------------------1.全局的block-----------------------------------------**/ /*1.全局的block**/ /* 只是操作自己的参数 不能操作其他任何的参数 **/ void  = ^ { NSLog(@"block1:%d", a); }; NSLog(@"block1_type = %@",block);//block1_type = <__NSGlobalBlock__: 0x10a1be0e0> /*-------------------2.分配到堆中的block--------------------------------**/ /* * 2.分配到堆中的block * 会分配到堆中的block * 即在arc中默认会将block从栈复制到堆上(arc 中 默认是 __strong 修饰), * 而在非arc中,则需要手动copy. * 在arc 中如果 block 中引用了其他的变量 (不管是局部变量还是全局变量),都会拷贝到堆中 **/ void  = ^{ /*1).这种情况调用的时候还是崩溃**/ //NSLog(@"block2:%d", weakSelf.add); /*2).这种情况调用的时候还是崩溃**/// __strong ViewController * strongSelf = weakSelf;// NSLog(@"block2:%d", strongSelf.add); /*3).这种情况调用的时候还是崩溃**/ //NSLog(@"block2:%d", self.add); NSLog(@"block2:%@", self); /* * 上面的情况调用崩溃,很可能是 block2 在viewdidLoad 结束后 ,又马上释放掉了 * 但是有个疑问就是 怎么block 里面引用了self 还是不行了呢? * 在touchesBegan中打印了 self.block2 的值 = null,说明的是 当前的block2 在 * 在viewdidLoad 结束后会马上的释放掉 并且block = nil (所以里面的不管copy 了多少东西都马上清空了); * 只有全局的block 还是 还是能看到地址 * 栈block 直接崩溃(可能是栈里面的东西 ios 系统没做处理,释放后没有让其值 = nil) ***/ }; NSLog(@"block2_type = %@",block2);//block2_type = <__NSMallocBlock__: 0x7fa9c2418d90> /*-------------------3.分配到栈中block--------------------------------**/ /* 3.分配到栈中(用__weak 来修饰) , 这个当在 其他地方调用的时候 很容易崩溃 **/ __weak void  = ^(){ NSLog(@"block3:%d", weakSelf.add); }; NSLog(@"block3_type = %@",block3);//block3_type = <__NSStackBlock__: 0x7fff50da8980> /*-------------------4.测试 --------------------------------**/ /* * 测试 * 我们用一个weak 的全局block 来引用 * 在touchBegan 中调用 **/ self.block1 = block; self.block2 = block2; self.block3 = block3; /* 在viewdidLoad 里面 都可以 正常的执行 ,但是在touchesBegan: 中就可能出现问题 **/ self.block1;//正常运行 self.block2();//正常运行 self.block3();//正常运行 }- touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event { NSLog(@"self.block1 = %@",self.block1);//<__NSGlobalBlock__: 0x102baf0f0> NSLog(@"self.block2 = %@",self.block2);// //NSLog(@"self.block3 = %@",self.block3);//直接崩溃 //self.block1;//正常运行 //self.block2();//直接崩溃 //self.block3();//直接崩溃}@end

那么请问:为什么 block 里面还需要写一个 strong self,如果不写会怎么样?

**3.总结 **1).关于 __weak typeof weakSelf = self;在block中 __strong ViewController * strongSelf = weakSelf;主要用在第三方的block 中,解释说,是为了防止block 提前释放,同时防止循环引用 ,很想 求一个例子,不写这个和写这个出现不同的结果。到目前为止 我个人理解是没用,没效果(真的很希望求一个例子)。2)block中 还是用strong 或者copy 拷贝到堆中,不要让其马上释放掉3)后续 在研究一下block

在 block 中先写一个 strong self,其实是为了避免在 block 的执行过程中,突然出现 self 被释放的尴尬情况。通常情况下,如果不这么做的话,还是很容易出现一些奇怪的逻辑,甚至闪退。

我们以AFNetworking中的AFNetworkReachabilityManager.m的一段代码举例:

__weak __typeof(self)weakSelf = self;
AFNetworkReachabilityStatusBlock callback = ^(AFNetworkReachabilityStatus status) {
   __strong __typeof(weakSelf)strongSelf = weakSelf;
   strongSelf.networkReachabilityStatus = status;
   if (strongSelf.networkReachabilityStatusBlock) {strongSelf.networkReachabilityStatusBlock(status);
   }
};

如果没有strongSelf的那行代码,那么后面的每一行代码执行时,self都可能被释放掉了,这样很可能造成逻辑异常。

特别是当我们正在执行 strongSelf.networkReachabilityStatusBlock(status); 这个 block闭包时,如果这个 block 执行到一半时 self 释放,那么多半情况下会 Crash。

这里有一篇文章详细解释了这个问题:
昨天的读者中,拓荒者 和 陈祥龙 同学在评论中也正确回答出了本题。

拓荒者:
1.在block里使用strongSelf是防止在block执行过程中self被释放。 2.可以通过在执行完block代码后手动把block置为nil来打破引用循环,AFNetworking就是这样处理的,避免使用者不了解引用循环造成内存泄露。实际业务中暂时没遇到这种需求,请巧哥指点什么情况下会有这种需求。

陈祥龙:
strongSelf 一般是在为了避免 block 回调时 weak Self变成了nil ,异步执行一些操作时可能会出现这种情况,不知道我说得对不对。因业务需要不能使用weakSelf 这种情况还真没遇到过

另外,还有读者提了两个有意思的问题,大家可以思考一下:
Yuen 提问:“数组” 和 “字典” 的 enumeratXXXUsingBlock: 是否要使用 weakSelf 和 strongSelf 呢?
潇湘雨同学提问:block 里 strong self 后,block 不是也会持有 self 吗?而 self 又持有 block ,那不是又循环引用了?

本文由永利402游戏网站-永利402com官方网站发布于网络编程,转载请注明出处:iOS 面试题(三)几时在 block 中无需运用 weakSel

关键词:

上一篇:Swift-粉碎动画效果

下一篇:没有了