基本概念
Block可以帮助我们组织独立的代码段,并提高复用性和可读性。
Block的好处,我总结了下主要有2点:1.用于回调特别方便,2.可以延长对象的作用区域。
为了性能,默认Block都是分配在stack(栈)上面的,所以它的作用区域就是当前函数。
int main() { int i = 1024; void (^blk)(void) = ^ { printf("%d\n", i); }; blk(); return 0; }
int (^oneFrom)(int) = ^(int anInt) { return anInt - 1; }; // 我们创建了一个内联块^(int anInt)... ,其函数体和结果被传到了另外一个名为OneFrom的Block。 printf("1 from 10 is %d", oneFrom(10)); // 打印出: "1 from 10 is 9" // 这个block函数(distanceTraveled)传入3个float型参数,返回float值。 float (^distanceTraveled) (float, float, float) = ^(float startingSpeed, float acceleration, float time) { float distance = (startingSpeed * time) + (0.5 * acceleration * time * time); return distance; };
Example:
// block中如果想访问外部变量,那么变量必须用 __block 进行修饰 __block int i = 10; void (^testBlock)() = ^(){ i++; }; testBlock(); NSLog(@"i现在的值:%d",i);
上例中的结果为11,那究竟是进行怎样的传值工作呢? 我们可以使用clang指令,查看生成的cpp文件。
假设上面代码是在main.m文件中,那么打开终端,
1. cd main.m文件所在的具体物理路径
2. clang -rewrite-objc main.m
3. open main.cpp
block部分生成的C++代码如下:
void (*testBlock)() = (void (*)())&__main_block_impl_0((void *)__main_block_func_0, &__main_block_desc_0_DATA, (__Block_byref_i_0 *)<span style="font-size:24px;color:#cc0000;"><strong>&i</strong></span>, 570425344);
block在UI具体操作中的使用
对上图进行大致的说明:
1. 左侧的图,是网易新闻结构图(左边LeftViewController是板块列表:新闻,本地... ; 右边则是具体板块的详细信息)
2. 中间的图,是在LeftViewController中自定义的block,点击不同的板块,均会调用leftBlock,只是block的输入参数为不同的板块信息而已。
3. 右侧的图,板块的详细信息(MainViewController),负责每个板块具体信息的展示工作
block的内存分析(下面一张图,我详细的剖析了block为什么要使用copy策略及解除循环引用的问题)
block中的循环引用
上图中,我大致介绍了block在MRC下循环引用。这里,我再具体详细说明一下block的循环引用问题
self.completionBlock = ^ { if (self.success) { self.success(self.responseData); } } };
__weak typeof(self) weakSelf = self; self.completionBlock = ^ { if (weakSelf.success) { weakSelf.success(weakSelf.responseData); } };