前言
草木有本心,何须美人折.JPG小时候家长和老师都教导我们,做人要善良要懂得吃亏.长大以后,才知道这样真的不好,有的时候你越是忍让越是糟糕,难受的是自己,有一句话说的很好:草木有本心,何须美人折? 活出自己最重要!
一丶Block储存的三种类型
1._NSConcretStackBlock(栈)
当block在函数内部,且定义的时候就使用了函数内部的变量,那么这个 block是存储在栈上的。
typedef void (^Block)(void);
- (void)setUp {
int val = 0;
Block block = ^(){
NSLog(@"val = %d",val);
};
block();
}
2._NSConcretGlobalBlock(全局)
当block定义在函数体外面,或者定义在函数体内部且当时函数执行的时候,block体中并没有需要使用函数内部的局部变量时,也就是block在函数执行的时候只是静静地待在一边定义了一下而不使用函数体的内容,那么block将会被编译器存储为全局block(代码段)。
typedef void (^Block)(void);
Block block;
- (void)setUp{
block = ^(){
int val = 0
NSLog(@"val = %d",val);
};
}
3._NSConcretMallocBlock(堆)
全局block存储在堆中,对全局block使用copy操作会返回原函数指针;而对栈中的block使用copy操作,会产生两个不同的block地址,也就是两个匿名函数的入口地址。
typedef void (^Block)(void);
@property (nonatomic, copy) Block block;//流经实例ID
self.block = ^(){
int val = 0
NSLog(@"val = %d",val);
};
self.block();
还有注意一下这点:
ARC机制优化会将stack的block,转为heap的block进行调用。也就是说在ARC环境下,你声明的block变量,无论用copy或是strong修饰,系统都会帮你把block复制到堆上.
二丶在Block里面修改普通外部变量
block其实是由四个结构体组装而成,用的不多,这里不多说,感兴趣的可以去研究一下源码.链接
我觉得block和一个函数差不多,都是一个代码块,等待被调用.
首先
NSString *str;
str 是个普通变量,储存在栈上,当函数走完以后,就会销毁.所以当block调用时已经找不到这个变量.
解决方法:
__block NSString *str;
这样写的话__block,会生成另外一个结构体,str引用计数加一.
三丶Block的循环引用
解决办法下面两个宏:
@weakify(self); // 定义了一个__weak的self_weak_变量
[RACObserve(self, name) subscribeNext:^(NSString *name) {
@strongify(self); // 局域定义了一个__strong的self指针指向self_weak
self.outputLabel.text = name;
}];
宏的实现
#define weakify(...) \\
autoreleasepool {} \\
metamacro_foreach_cxt(rac_weakify_,, __weak, __VA_ARGS__)
#define strongify(...) \\
try {} @finally {} \\
_Pragma("clang diagnostic push") \\
_Pragma("clang diagnostic ignored \\"-Wshadow\\"") \\
metamacro_foreach(rac_strongify_,, __VA_ARGS__) \\
_Pragma("clang diagnostic pop")
简单来说:
__weak typeof(self) weakSelf = self;
self.Button.rac_command = [[RACCommand alloc] initWithEnabled:textSig signalBlock:^RACSignal *(NSString * input) {
__strong typeof(weakSelf) strongSelf = weakSelf;
return nil;
}];
网友评论