OC Block 循环引用
一、什么是Block
1、Block是iOS中一种比较特殊的数据类型:
2、既然是数据类型,那么就可以通过该数据类型声明变量,并保存数据.Block数据类型不是用来保存int、double、NSString等数据,而是用来保存一段代码的。既然有变量可以保存一段代码,那么也就意味着可以把一段代码作为参数传递了。
3、Block是苹果官方特别推荐使用的数据类型,应用场景比较广泛。
1)动画
2)多线程
3)集合遍历
4)网络请求回调
4、Block的作用
1)用来保存某一段代码,可以再恰当的时候取出来调用
2)类似于函数和方法
5、语法介绍 如何声明Block
1)无参数,无返回值
2)带一个参数,无返回值
3)带两个参数,一个返回值
6、Block的主成员素跟函数类似
1)返回值
2)形式参数
3)实际参数
7、Block的定义格式
返回值类型 (^block变量名)(形参列表)= ^(形参列表) {
};
没有参数可以写void,比如:int (^blockname)(viod);
8、调用Block保存的代码
block变量名(实参);
1)使用typedef定义block类型。定义好以后就可以像普通数据类型那样使用了:typedef返回值类型(^block类型名称)(形参列表);
二、使用注意
1)默认情况下,Block内部不能修改外面的局部变量
2)Block内部可以修改使⽤用__block修饰的局部变量(如果想修改请使⽤用__block 修饰)
3)Block调⽤用前注意判断是否为nil,否则可能会报错!
4)使⽤Xcode用inlineBlock⾃自动⽣生成block定义代码(辅助记忆)
5)block在ARC中和MRC中的用法有什么区别,需要注意什么
不管是ARC和MRC,block都应该用copy操作来持有
应用避免循环应用
ARC: __weak、__unscafe_unretained
MRC:__block
三、三种解决循环引用的方法,好废话不多说,上代码;
@interface ViewController : UIViewController
@end
#import "NetWorkTools.h"
@interface ViewController ()
@property (nonatomic, strong) NetWorkTools *tools;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
//self.tools = [NetWorkTools alloc]init] 会造成循环引用
//第三种解决方式
//__unsafe_unretained 和 assgin关键字 效果一致
//EXC_BAD_ACCESS 在MRC时代 最常见的错误 坏内存地址访问 野指针
//当对象被系统回收时 它的内存地址 不会自动指向nil
// __unsafe_unretained 是 iOS4.0推出
self.tools = [[NetWorkTools alloc]init];
__unsafe_unretained typeof (self) weakSelf = self;
[self.tools loadData:^(NSString *html) {
NSLog(@"%@ %@",html,weakSelf.view);
}];
}
- (void)metmod2{
//第二种解决方法
//__weak 声明一个弱引用类型的自己 来解除
//__weak 和 weak 当对象被系统收回时 它的内存地址 会自动指向 nil
//__weak typeof(self) weakSelf = self;
self.tools = [[NetWorkTools alloc]init];
__weak typeof (self) weakSelf = self;
[self.tools loadData:^(NSString *html) {
NSLog(@"%@ %@",html,weakSelf.view);
}];
}
//第一种解决方法
- (void) metmod1{
//self.tools = [NetWorkTools alloc]init] 会造成循环引用
NetWorkTools *tools = [[NetWorkTools alloc]init];
[tools loadData:^(NSString *html) {
NSLog(@"%@ %@",html,self.view);
self.view.backgroundColor = [UIColor redColor];
}];
}
//工作中会常见到这样的
- (void)metmod {
__weak typeof(self) weakSelf = self;
[self.tools loadData:^(NSString *html) {
//用强引用对弱引用的对象 做一次'强'的操作
__strong typeof(self) strongSelf = weakSelf;
NSLog(@"%@%@",html,strongSelf.view);
strongSelf.view.backgroundColor = [UIColor redColor];
}];
}
- (void)dealloc {
NSLog(@"view 88");
}
@interface NetWorkTools : NSObject
- (void) loadData:(void(^)(NSString *html))finisfedCallBack;
@interface NetWorkTools ()
@property (nonatomic, copy) void(^finishedBlock)(NSString *);
@end
@implementation NetWorkTools
- (void)loadData:(void (^)(NSString *))finishedCallBack {
//开始记录Block
self.finishedBlock = finishedCallBack;
dispatch_async(dispatch_get_global_queue(0, 0), ^{
//执行耗时操作
[NSThread sleepForTimeInterval:3];
NSLog(@"开始加载数据");
dispatch_async(dispatch_get_main_queue(), ^{
[self working];
});
});
}
- (void)working {
//执行Block
if (self.finishedBlock) {
self.finishedBlock(@"<html>");
}
}
- (void)dealloc {
NSLog(@"Tools 挂了");
}
有什么问题请大家提出,一起修改、学习;