Block的种类
Block分为三类
1.NSGlobalBlock: 静态区
2.NSMallocBlock: 堆 Block
3.NSStackBlock: 栈Block
void(^fisrtBlcok)(void) = ^{
NSLog(@"blcok");
};
NSLog(@"第一种%@",fisrtBlcok);
NSInteger a = 10;
void(^blcok)(void) = ^{
NSLog(@"Hello block = %ld", a);
};
blcok();
NSLog(@"第二种%@",blcok);
NSLog(@"第三种Block: %@",^{
NSLog(@"===%ld",a);
});
解决Block循环引用方法
- Strong weak dance 这个不多说
self.name = @"Eddiegooo";
__weak typeof(self) weakSelf = self;
self.testBlock = ^{
__strong typeof(weakSelf) strongSelf = weakSelf;
NSLog(@"%@", strongSelf.name);
};
2.mrc: __block
__block SecViewController *weakVC = self; //这里是重新copy了一份:
//weakVC ---> self ---> testBlock ---> weakVC = nil
self.testBlock = ^{
NSLog(@"%@",weakVC.name);
//注意 必须置为nil
weakVC = nil;
};
//这里必须还要掉用一下
self.testBlock(); //调用Block, weakVC 就置nil了
3.把self当参数传递方式
Block 循环引用: self ---> block ---> self.
self持有Block, Block持有self。 这时打破这个环即可解决。
self ----> block ----> vc
typedef void(^block)(SecViewController *vc);
@interface SecViewController ()
@property (nonatomic, strong) NSString *name;
@property (nonatomic, copy) block testBlock;
@end
self.testBlock = ^(SecViewController *vc) {
NSLog(@"%@", vc.name);
};
self.testBlock(self); //self当临时变量参数
深究Block原理
1.创建一个c文件
终端: vim block.c
写入C函数:
#include <stdio.h>
int main() {
int a = 10;
void(^block)(void) = ^{
printf("%d", a);
};
block();
return 0;
}
2.执行C函数
gcc block.c
输入一个a.out 的可执行文件。
./a.out
执行它。 可以看到打印结果。
clang -rewrite-objc block.c
执行完得到block.cpp这个文件,打开看下什么东西。
打开这个block.cpp 文件,一脸懵逼啊
懵逼文件.png
别怕慢慢看,其实这就是消息转发。 我们把文件拉倒最下面,就能找到main函数了。
main 函数.png
然后在点到文件里面去看下什么意思,值拷贝。
当我们把block.c 文件里,int a = 10, 前面加上__block ,在clang 一次。发现main函数变化很大哇:
__block 后的main函数.png
__block 这个就是浅copy作用。
Block应用:链式编程 + 函数式编程
链式编程:
//想要使用s链式编程,用点语法调用函数,返回IMP的第一个参数self
- (ViewController *)select {
NSLog(@"Select");
return self;
}
//返回一个Block参数
- (NSString *(^)(NSString *))where {
NSString *(^block)(NSString *) = ^(NSString *word) {
return [NSString stringWithFormat:@"向大家说:%@", word];
};
return block;
}
这样就可以调用点语法函数了。
NSLog(@"%@",self.select.where(@"niubi"));
函数式编程:
y= f(x) ---> y = f(f(x));
//函数式Demo
- (void)functionCompletion:(void(^)(NSString *))completion {
if (completion) {
//灵活 异步 传值
completion(@"调用完成了");
}
}
使用:
//把完成的结果传过来使用
[self functionCompletion:^(NSString *word) {
NSLog(@"%@",word);
}];
类似这种应用很多吧,在网络请求用到的最多吧。
函数式编程方法封装:
比如UIButton addtarget。 Button和方法实现分开的。 这时候可以用函数式编程,将定义button和方法放在一起,用Block回调。
网友评论