zoukankan      html  css  js  c++  java
  • block 解析

    block形参

    之前漏了一篇block形参的介绍,这里给补上。

    block形参就是定义block带的参数,和函数的参数使用一样,我们可以在block随意使用修改block形参。

    我们来看个例子:

    我们声明了两个NSString 指针_p1 _p2、int 型_p3、可变数组_p4,并把这些参数传入block,在block内修改。

    -(void )test3
    {
        NSString *_p1=[NSString stringWithFormat:@"hello %@",@"world11"];
        NSString *_p2=[NSString stringWithFormat:@"hello %@",@"world12"];
        int _p3=1;
        NSMutableArray *_p4=[[NSMutableArray alloc]init];
        //初始值
        NSLog(@"init p1:%@,%p,%p",_p1,_p1,&_p1);
        NSLog(@"init p2:%@,%p,%p",_p2,_p2,&_p2);
        NSLog(@"init p3:%d,%p",_p3,&_p3);
        NSLog(@"init p4:%@,%p,%p",_p4,_p4,&_p4);
        void (^myBlock)(NSString *,NSString **,int,NSMutableArray *) = ^(NSString *p1,NSString **p2,int p3,NSMutableArray * p4) {
            //block内赋值
            p1=@"21";
            *p2=@"22";
            p3=23;
            [p4 addObject:@"23"];
            NSLog(@"excuteing p1:%@,%p,%p",p1,p1,&p1);
            NSLog(@"excuteing p2:%@,%p,%p,%p",*p2,*p2,p2,&p2);
            NSLog(@"excuteing p3:%d,%p",p3,&p3);
            NSLog(@"excuteing p4:%@,%p,%p",p4,p4,&p4);
        };
        myBlock(_p1,&_p2,_p3,_p4);
        //block执行后
        NSLog(@"excuteafter p1:%@,%p,%p",_p1,_p1,&_p1);
        NSLog(@"excuteafter p2:%@,%p,%p",_p2,_p2,&_p2);
        NSLog(@"excuteafter p3:%d,%p",_p3,&_p3);
        NSLog(@"excuteafter p4:%@,%p,%p",_p4,_p4,&_p4);
    }

    输出日志:

    2014-07-31 14:17:06.774 Test[3655:60b] init p1:hello world11,0x16537b20,0x27df8990
    2014-07-31 14:17:06.776 Test[3655:60b] init p2:hello world12,0x1652d760,0x27df898c
    2014-07-31 14:17:06.778 Test[3655:60b] init p3:1,0x27df8988
    2014-07-31 14:17:06.779 Test[3655:60b] init p4:(
    ),0x1652b6d0,0x27df8984
    2014-07-31 14:17:06.781 Test[3655:60b] excuteing p1:21,0x11a08,0x27df893c
    2014-07-31 14:17:06.782 Test[3655:60b] excuteing p2:22,0x11a18,0x27df897c,0x27df8938
    2014-07-31 14:17:06.783 Test[3655:60b] excuteing p3:23,0x27df8934
    2014-07-31 14:17:06.784 Test[3655:60b] excuteing p4:(
        23
    ),0x1652b6d0,0x27df8930
    2014-07-31 14:17:06.785 Test[3655:60b] excuteafter p1:hello world11,0x16537b20,0x27df8990
    2014-07-31 14:17:06.786 Test[3655:60b] excuteafter p2:22,0x11a18,0x27df898c
    2014-07-31 14:17:06.787 Test[3655:60b] excuteafter p3:1,0x27df8988
    2014-07-31 14:17:06.788 Test[3655:60b] excuteafter p4:(
        23
    ),0x1652b6d0,0x27df8984

    从日志可以看出:

    • 我们把指针_p1(NSString *)传入block,传参数的过程其实可以理解为用新的指针指向  _p1所指向的内存地址。这时候在block内部修改指针指向,只是修改了block形参的指针的指向,所以block内部p1的内容和block外部_p1的不一样。
    • 我们把指针_p4(NSMutableArray *)传入block,传参数的过程和上面一样,用了一个新的指针指向  参数所指向的内存地址,在block内部对 形参指针指向的内存进行修改,即操作的是同一片内存,所以能同步到block外部。
    • 我们把指针_p2(NSString **)传到了block内部,传递的是指针的地址,我们在block内部修改*p2,其实是修改 指针p2 指向的指针  指向的内存地址,也能同步到block外部。
    • 因为_p3是值传递,所以block内部修改不会影响外部,这个和函数一样。

    我们来看看block对行参变量的处理:

    这是block结构体,并没有生成成员 对形参进行引用

    struct __KDBlockTest__test3_block_impl_0 {
      struct __block_impl impl;
      struct __KDBlockTest__test3_block_desc_0* Desc;
      __KDBlockTest__test3_block_impl_0(void *fp, struct __KDBlockTest__test3_block_desc_0 *desc, int flags=0) {
        impl.isa = &_NSConcreteStackBlock;
        impl.Flags = flags;
        impl.FuncPtr = fp;
        Desc = desc;
      }
    };

    我们看block实现的函数,对变量的访问,都是通过形参来实现的,并没有通过结构体的成员

    static void __KDBlockTest__test3_block_func_0(struct __KDBlockTest__test3_block_impl_0 *__cself, NSString *p1, NSString **p2, int p3, NSMutableArray *p4) {
    
    
            p1=(NSString *)&__NSConstantStringImpl__var_folders_5l_2l25j3tn0wl_3zy1hpsq1rhc0000gp_T_KDBlockTest_654672_mi_9;
            *p2=(NSString *)&__NSConstantStringImpl__var_folders_5l_2l25j3tn0wl_3zy1hpsq1rhc0000gp_T_KDBlockTest_654672_mi_10;
            p3=23;
            ((void (*)(id, SEL, id))(void *)objc_msgSend)((id)p4, sel_registerName("addObject:"), (id)(NSString *)&__NSConstantStringImpl__var_folders_5l_2l25j3tn0wl_3zy1hpsq1rhc0000gp_T_KDBlockTest_654672_mi_11);
            NSLog((NSString *)&__NSConstantStringImpl__var_folders_5l_2l25j3tn0wl_3zy1hpsq1rhc0000gp_T_KDBlockTest_654672_mi_12,p1,p1,&p1);
            NSLog((NSString *)&__NSConstantStringImpl__var_folders_5l_2l25j3tn0wl_3zy1hpsq1rhc0000gp_T_KDBlockTest_654672_mi_13,*p2,*p2,p2,&p2);
            NSLog((NSString *)&__NSConstantStringImpl__var_folders_5l_2l25j3tn0wl_3zy1hpsq1rhc0000gp_T_KDBlockTest_654672_mi_14,p3,&p3);
            NSLog((NSString *)&__NSConstantStringImpl__var_folders_5l_2l25j3tn0wl_3zy1hpsq1rhc0000gp_T_KDBlockTest_654672_mi_15,p4,p4,&p4);
        }

    下面是我们的测试函数,看红色部分,是通过函数参数传递,和函数调用一样,和block内使用局部变量、静态变量、成员变量还是有很大区别的,并没有截获变量。

    static void _I_KDBlockTest_test3(KDBlockTest * self, SEL _cmd) {
        NSString *_p1=((NSString *(*)(id, SEL, NSString *, ...))(void *)objc_msgSend)((id)objc_getClass("NSString"), sel_registerName("stringWithFormat:"), (NSString *)&__NSConstantStringImpl__var_folders_5l_2l25j3tn0wl_3zy1hpsq1rhc0000gp_T_KDBlockTest_654672_mi_1, (NSString *)&__NSConstantStringImpl__var_folders_5l_2l25j3tn0wl_3zy1hpsq1rhc0000gp_T_KDBlockTest_654672_mi_2);
        NSString *_p2=((NSString *(*)(id, SEL, NSString *, ...))(void *)objc_msgSend)((id)objc_getClass("NSString"), sel_registerName("stringWithFormat:"), (NSString *)&__NSConstantStringImpl__var_folders_5l_2l25j3tn0wl_3zy1hpsq1rhc0000gp_T_KDBlockTest_654672_mi_3, (NSString *)&__NSConstantStringImpl__var_folders_5l_2l25j3tn0wl_3zy1hpsq1rhc0000gp_T_KDBlockTest_654672_mi_4);
        int _p3=1;
        NSMutableArray *_p4=((id (*)(id, SEL))(void *)objc_msgSend)((id)((id (*)(id, SEL))(void *)objc_msgSend)((id)objc_getClass("NSMutableArray"), sel_registerName("alloc")), sel_registerName("init"));
    
        NSLog((NSString *)&__NSConstantStringImpl__var_folders_5l_2l25j3tn0wl_3zy1hpsq1rhc0000gp_T_KDBlockTest_654672_mi_5,_p1,_p1,&_p1);
        NSLog((NSString *)&__NSConstantStringImpl__var_folders_5l_2l25j3tn0wl_3zy1hpsq1rhc0000gp_T_KDBlockTest_654672_mi_6,_p2,_p2,&_p2);
        NSLog((NSString *)&__NSConstantStringImpl__var_folders_5l_2l25j3tn0wl_3zy1hpsq1rhc0000gp_T_KDBlockTest_654672_mi_7,_p3,&_p3);
        NSLog((NSString *)&__NSConstantStringImpl__var_folders_5l_2l25j3tn0wl_3zy1hpsq1rhc0000gp_T_KDBlockTest_654672_mi_8,_p4,_p4,&_p4);
        void (*myBlock)(NSString *,NSString **,int,NSMutableArray *) = (void (*)(NSString *, NSString **, int, NSMutableArray *))&__KDBlockTest__test3_block_impl_0((void *)__KDBlockTest__test3_block_func_0, &__KDBlockTest__test3_block_desc_0_DATA);
        ((void (*)(__block_impl *, NSString *, NSString **, int, NSMutableArray *))((__block_impl *)myBlock)->FuncPtr)((__block_impl *)myBlock, _p1, &_p2, _p3, _p4);//block 执行
    
        NSLog((NSString *)&__NSConstantStringImpl__var_folders_5l_2l25j3tn0wl_3zy1hpsq1rhc0000gp_T_KDBlockTest_654672_mi_16,_p1,_p1,&_p1);
        NSLog((NSString *)&__NSConstantStringImpl__var_folders_5l_2l25j3tn0wl_3zy1hpsq1rhc0000gp_T_KDBlockTest_654672_mi_17,_p2,_p2,&_p2);
        NSLog((NSString *)&__NSConstantStringImpl__var_folders_5l_2l25j3tn0wl_3zy1hpsq1rhc0000gp_T_KDBlockTest_654672_mi_18,_p3,&_p3);
        NSLog((NSString *)&__NSConstantStringImpl__var_folders_5l_2l25j3tn0wl_3zy1hpsq1rhc0000gp_T_KDBlockTest_654672_mi_19,_p4,_p4,&_p4);
    }

    总结:

    • 对于block形参,block不会对形参、实参强引用,调用是通过参数传递实现的(block结构体内部没有成员引用)
    • 和函数调用一样,block内部可以修改形参,并且影响到实参。
  • 相关阅读:
    java.lang.NoSuchMethodError
    asm相关内容想下载(包括 jar 包)
    Initialization of bean failed; nested exception is java.lang.NoClassDefFoundError: org/objectweb/asm/Type
    用Navicat连接mysql报错:2003-Can't connect to MySql server on '10.100.0.109'(10039)
    The type java.lang.reflect.AnnotatedElement cannot be resolved. It is indirectly referenced from required .class files
    The type java.lang.CharSequence cannot be resolved. It is indirectly referenced from required .class files
    交通测速方式
    卡口和电子警察的区别
    Myeclipse连接Mysql数据库时报错:Error while performing database login with the pro driver:unable
    在window上安装mysql
  • 原文地址:https://www.cnblogs.com/NarutoYq/p/3880851.html
Copyright © 2011-2022 走看看