美文网首页
block的相关技术点

block的相关技术点

作者: 雪丹妮_66865 | 来源:发表于2019-09-25 15:29 被阅读0次

void test1() {
int a = 10;

void (^block)(void) = ^{
    NSLog(@"a is %d", a);
};

a = 20;

block();//10

}

void test2() {
__block int a = 10;

void (^block)(void) = ^{
    NSLog(@"a is %d", a);
};

a = 20;

block();//20

}

void test3() {
static int a = 10;

void (^block)(void) = ^{
    NSLog(@"a is %d", a);
};

a = 20;

block();//20

}

int a = 10;
void test4() {
void (^block)(void) = ^{
NSLog(@"a is %d", a);
};

a = 20;

block();//20

}

造成这样的原因是:传值和传址。
使用clang命令可以将代码编译成C++:

void test1() {
int a = 10;

void (*block)(void) = ((void (*)())&__test1_block_impl_0((void *)__test1_block_func_0, &__test1_block_desc_0_DATA, a));

a = 20;

((void (*)(__block_impl *))((__block_impl *)block)->FuncPtr)((__block_impl *)block);

}

void test2() {
attribute((blocks(byref))) __Block_byref_a_0 a = {(void*)0,(__Block_byref_a_0 *)&a, 0, sizeof(__Block_byref_a_0), 10};

void (*block)(void) = ((void (*)())&__test2_block_impl_0((void *)__test2_block_func_0, &__test2_block_desc_0_DATA, (__Block_byref_a_0 *)&a, 570425344));

(a.__forwarding->a) = 20;

((void (*)(__block_impl *))((__block_impl *)block)->FuncPtr)((__block_impl *)block);

}

void test3() {
static int a = 10;

void (*block)(void) = ((void (*)())&__test3_block_impl_0((void *)__test3_block_func_0, &__test3_block_desc_0_DATA, &a));

a = 20;

((void (*)(__block_impl *))((__block_impl *)block)->FuncPtr)((__block_impl *)block);

}

void test4() {
void (block)(void) = ((void ()())&__test4_block_impl_0((void *)__test4_block_func_0, &__test4_block_desc_0_DATA));

a = 20;

((void (*)(__block_impl *))((__block_impl *)block)->FuncPtr)((__block_impl *)block);

}

总结:只有普通局部变量是传值,其他情况都是传址。

3、block的内存管理

  1. 无论当前环境是ARC还是MRC,只要block没有访问外部变量,block始终在全局区
    2.MRC情况下,
    block如果访问外部变量,block在栈里
    不能对block使用retain,否则不能保存在堆里
    只有使用copy才能放到堆里
    3.ARC情况下
    block如果访问外部变量,block在堆里
    block可以使用copy和strong,并且block是一个对象

4、block的循环引用
如果要在block中直接使用外部强指针会发生错误,使用以下代码在block外部实现可以解决
__weak typeof(self) weakSelf = self;
但是如果在block内部使用延时操作还是用弱指针的话回去不到该弱指针,需要在block内部再将弱指针强引用以下
__strong typeof(self) strongSelf = weakSelf;

5、block中的weak self,是任何时候都需要加的么?
不是什么任何时候都需要加的,不过任何时候都添加似乎总是好的。只要出现像self->block->self.property/self->Ivar这样的结构连时,才会出现循环引用问题。

6、block的变量传递
如果block访问的外部变量是局部变量,那么就是值传递,外界改了,不会影响里面
如果block访问的外部变量是__block或者static修饰,或者是全局变量,那么就是指针传递,block里面的值和外界同一个变量,外界改变,里面也会改变
验证一下是不是这样
通过Clang来将main.m文件编译成C++
在终端输入如下命令clang -rewrite-objc main.m

void(block)() = ((void ()())&__main_block_impl_0((void )__main_block_func_0, &__main_block_desc_0_DATA, (__Block_byref_a_0 )&a, 570425344));
void(
block)() = ((void (
)())&__main_block_impl_0((void *)__main_block_func_0,

可以看到在编译后的代码最后可以发现被__block修饰过的变量使用的是&a,而局部变量是a

7、block的注意点
在block内部使用外部指针且会造成循环引用情况下,需要用__weak修饰外部指针
__weak typeof(self) weakSelf = self;
在block内部如果使用了延时函数还是用弱指针会取不到该指针,因为已经被销毁了,需要在block内部再将弱指针重新强引用一下
__strong typeof(self) strongSelf = weakSelf;
如果需要在block内部改变外部变量的话,需要在用__block修饰外部变量

相关文章

  • block的相关技术点

    void test1() {int a = 10; } void test2() {__block int a =...

  • Block 初见

    Block 初见 介绍 iOS block 的相关知识 目录 Block 背景知识 Block 使用方式 Bloc...

  • 21·iOS 面试题·__block 在 ARC 和 MRC 下

    前言 对于 Block 以及 __block 相关的知识点,之前的面试题已经涉及过:04·iOS 面试题·Bloc...

  • block相关

    是写在方法里的,在方法里定义个block,有返回值的,以;结尾,block只有被调用的时候才能执行 {} 里的代码...

  • Block相关

    bock常用写法: 1、无返回值 & 无参数 2、有返回值 & 无参数 3、有返回值 & 有参数 4、 block...

  • Block相关

    Block基本使用 1.1、block声明:返回值(^block变量名)(参数)void(^block)(); 1...

  • Block相关

    https://www.jianshu.com/p/4e79e9a0dd82

  • Block相关

  • Block相关

    Block 一:结构相关Block是一个包含了上下文变量的对象,该对象包含了_block_impl结构体,上下文变...

  • Block相关

    类型 1.NSGloabalBlock 全局block,存储在全局区 该block无参数,无返回值,内部也没有引用...

网友评论

      本文标题:block的相关技术点

      本文链接:https://www.haomeiwen.com/subject/dqwquctx.html