美文网首页
OC语言day06-15Block注意事项

OC语言day06-15Block注意事项

作者: liyuhong165 | 来源:发表于2016-06-20 00:26 被阅读61次

    pragma mark Block注意事项

    pragma mark 概念

    /**
     1.为什么不加 __block不能在block中修改外界变量的值 (值传递)
     2.为什么加 __block能在block中修改外界变量的值 (地址传递)
     
     3.block 是 存储在堆中 还是 栈中 (默认在栈,copy到堆)
     4.如果在block中访问了外界的对象, 一定要给对象加上 __block, 只要加上了__block, 哪怕block 在堆中 , 也不会对外界的对象 进行retain操作
     */
    

    pragma mark 代码

    #import <Foundation/Foundation.h>
    #pragma mark 类
    #import "Person.h"
    #pragma mark main函数
    int main(int argc, const char * argv[])
    {
    #warning 1.block中 可以访问外面的变量
        /*
        int a = 10;
        void (^myBlock)() = ^{
            NSLog(@"a = %i",a);
        };
        
        // 调用block
        myBlock();
         */
        
    #warning 2.block 中 可以定义和外界 同名的变量, 并且如果 在block 中定义了和外名同名的变量, 在block中访问的事block中的变量
        /*
        int a = 10;
        void (^myBlock)() = ^{
            int a = 20;
            NSLog(@"a = %i",a);
        };
        
        // 调用block
        myBlock();
        */
        
    #warning 3.block 默认情况下, 不可以在block中修改外界变量的值
        // 因为block中的变量 和 外界的变量 并不是同一个变量
        // 如果block中 访问了外界的变量, block 会将外界的变量 拷贝一份到堆内存中
        // 因为block中使用的外界变量 是 copy的, 所以在调用之前 修改 外界变量的值, 不会影响到block 中 copy的值
        
    #pragma mark code
        /*
        int a = 10;
        NSLog(@"&a = %p",&a);   // 0x7fff5fbff7dc
        void (^myBlock)() = ^{
    //        a = 50;
            NSLog(@"&a = %p",&a);   // 0x1005002f0
            NSLog(@"a = %i",a);
        };
    
        a = 20;
        
        // 调用block
        myBlock();
        */
        
    #warning 4.block 不默认情况下, 可以在block中修改外界变量的值
        // 如果想在block中 修改外界变量的值, 必须在外界变量 前面加上 __block
        // 如果在block中 修改了外界变量的值, 会影响外界变量的值
        
    #pragma mark code
        /*
        __block int a = 10;
        NSLog(@"&a = %p",&a);   // 0x7fff5fbff7d8
        void (^myBlock)() = ^{
            a = 50;
            NSLog(@"&a = %p",&a);   // 0x103200278
            NSLog(@"a = %i",a);
        };
        // 调用block
        myBlock();
        NSLog(@"a = %i",a);
         */
        
    #pragma mark 5.深入了解 为什么添加__block 就可以修改外界变量的值
        /**
         将.m文件 转换成c++文件(为什么调用方法 称为 发消息)
         通过终端
         到当前的路径 cc -rewrite-objc main.m 此时 多了一个文件
         
         打开.cpp
         NSXPCListenerEndpoint 搜索 从最后一个前面的代码全部删除
         */
    #warning 1.为什么不加 __block不能在block中修改外界变量的值 (值传递)
    #pragma mark 1.code
        /*
        int a = 10;
        void (^myBlock)() = ^{
    //        a = 20;
            NSLog(@"a = %i",a);
        };
        myBlock();
        */
    #pragma mark cpp code
        /**
         // __main_block_impl_0 这一块是一个结构体
         
         int a = 10; // 如果没有添加 __block是值传递
         void (*myBlock)() = &__main_block_impl_0(__main_block_func_0, &__main_block_desc_0_DATA, a)); // 基本数据类型 作为函数参数传递 是值传递 在内部修改 不会影响外部
         (myBlock)->FuncPtr)(myBlock);
         */
        
    #warning 2.为什么加 __block能在block中修改外界变量的值 (地址传递)
    #pragma mark 2.code
        /*
        __block int a = 10;
        void (^myBlock)() = ^{
            a = 20;
            NSLog(@"a = %i",a);
        };
        myBlock();
         */
        
    #pragma mark cpp code
        /**
         // __main_block_impl_0 这一块是一个结构体
         // &a 这里传递的是一个 地址
         //    a = 10;  // 如果加上 __block 之后 就是地址传递, 所以可以在block中 修改外界变量的值
         //    void (*myBlock)() = &__main_block_impl_0(__main_block_func_0, &__main_block_desc_0_DATA, &a, 570425344));
         */
        
    #pragma mark 6.block 是 存储在堆中 还是 栈中 (默认在栈,copy到堆)
        // 默认情况下 block存储在栈中,  如果对block进行一个copy操作,block会转移到堆中
        // 如果block在 栈中, block中访问了外界的对象, 那么不会对 对象进行retain操作。
        // 但是block在 堆中, block中访问了外界的对象, 那么会对 外界的对象进行一次 retain
        
        // 如果在block中访问了外界的对象, 一定要给对象加上 __block, 只要加上了__block, 哪怕block 在堆中 , 也不会对外界的对象 进行retain操作
    //    Person *p = [[Person alloc]init]; // 1
        __block Person *p = [[Person alloc]init]; // 1
        NSLog(@"retainCount = %lu",[p retainCount]);    // 1
        
        void (^myBlock)() = ^{
            NSLog(@"a = %@",p); // 1 没有加上 __block 是2
            NSLog(@"block retainCount = %lu",[p retainCount]); // 1
        };
        
        Block_copy(myBlock);    // 2 这里也会对外界的对象进行一次retain操作
        myBlock();
        
        [p release];    // 0 没有加上 __block 是1 出现内存泄露
        
        return 0;
    }
    #pragma mark 3. 添加__block 反编译文件 修改完毕
    //struct __Block_byref_a_0 {
    //    void *__isa;
    //    __Block_byref_a_0 *__forwarding;
    //    int __flags;
    //    int __size;
    //    int a;
    //};
    //
    //struct __main_block_impl_0 {
    //    struct __block_impl impl;
    //    struct __main_block_desc_0* Desc;
    //    __Block_byref_a_0 *a; // by ref
    //    __main_block_impl_0(void *fp, struct __main_block_desc_0 *desc, __Block_byref_a_0 *_a, int flags=0) : a(_a->__forwarding) {
    //        impl.isa = &_NSConcreteStackBlock;
    //        impl.Flags = flags;
    //        impl.FuncPtr = fp;
    //        Desc = desc;
    //    }
    //};
    //static void __main_block_func_0(struct __main_block_impl_0 *__cself) {
    //    __Block_byref_a_0 *a = __cself->a; // bound by ref
    //    
    //    (a->__forwarding->a) = 20;
    //    NSLog((NSString *)&__NSConstantStringImpl__var_folders_7r_m33tlwsx3w79b9r0btsyv8q80000gp_T_main_e0c860_mi_0,(a->__forwarding->a));
    //}
    //static void __main_block_copy_0(struct __main_block_impl_0*dst, struct __main_block_impl_0*src) {_Block_object_assign((void*)&dst->a, (void*)src->a, 8/*BLOCK_FIELD_IS_BYREF*/);}
    //
    //static void __main_block_dispose_0(struct __main_block_impl_0*src) {_Block_object_dispose((void*)src->a, 8/*BLOCK_FIELD_IS_BYREF*/);}
    //
    //static struct __main_block_desc_0 {
    //    size_t reserved;
    //    size_t Block_size;
    //    void (*copy)(struct __main_block_impl_0*, struct __main_block_impl_0*);
    //    void (*dispose)(struct __main_block_impl_0*);
    //} __main_block_desc_0_DATA = { 0, sizeof(struct __main_block_impl_0), __main_block_copy_0, __main_block_dispose_0};
    //int main(int argc, const char * argv[])
    //{
    //    a = 10;
    //    void (*myBlock)() = &__main_block_impl_0(__main_block_func_0, &__main_block_desc_0_DATA, &a, 570425344));
    //    return 0;
    //}
    //static struct IMAGE_INFO { unsigned version; unsigned flag; } _OBJC_IMAGE_INFO = { 0, 2 };
    
    
    #pragma mark 1.没有添加__block 反编译文件 修改完毕
    /*
     修改完毕的
     .cpp
     
     struct __main_block_impl_0 {
     struct __block_impl impl;
     struct __main_block_desc_0* Desc;
     int a;
     __main_block_impl_0(void *fp, struct __main_block_desc_0 *desc, int _a, int flags=0) : a(_a) {
     impl.isa = &_NSConcreteStackBlock;
     impl.Flags = flags;
     impl.FuncPtr = fp;
     Desc = desc;
     }
     };
     static void __main_block_func_0(struct __main_block_impl_0 *__cself) {
     int a = __cself->a; // bound by copy
     
     
     NSLog((NSString *)&__NSConstantStringImpl__var_folders_7r_m33tlwsx3w79b9r0btsyv8q80000gp_T_main_3b2773_mi_0,a);
     }
     
     static struct __main_block_desc_0 {
     size_t reserved;
     size_t Block_size;
     } __main_block_desc_0_DATA = { 0, sizeof(struct __main_block_impl_0)};
     int main(int argc, const char * argv[])
     {
     int a = 10;
     void (*myBlock)() = &__main_block_impl_0(__main_block_func_0, &__main_block_desc_0_DATA, a));
     (myBlock)->FuncPtr)(myBlock);
     
     return 0;
     }
     static struct IMAGE_INFO { unsigned version; unsigned flag; } _OBJC_IMAGE_INFO = { 0, 2 };
     */
    
    #pragma mark 2.__block反编译文件 未修改的
    /*
     struct __main_block_impl_0 {
     struct __block_impl impl;
     struct __main_block_desc_0* Desc;
     int a;
     __main_block_impl_0(void *fp, struct __main_block_desc_0 *desc, int _a, int flags=0) : a(_a) {
     impl.isa = &_NSConcreteStackBlock;
     impl.Flags = flags;
     impl.FuncPtr = fp;
     Desc = desc;
     }
     };
     static void __main_block_func_0(struct __main_block_impl_0 *__cself) {
     int a = __cself->a; // bound by copy
     
     
     NSLog((NSString *)&__NSConstantStringImpl__var_folders_7r_m33tlwsx3w79b9r0btsyv8q80000gp_T_main_3b2773_mi_0,a);
     }
     
     static struct __main_block_desc_0 {
     size_t reserved;
     size_t Block_size;
     } __main_block_desc_0_DATA = { 0, sizeof(struct __main_block_impl_0)};
     int main(int argc, const char * argv[])
     {
     int a = 10;
     void (*myBlock)() = ((void (*)())&__main_block_impl_0((void *)__main_block_func_0, &__main_block_desc_0_DATA, a));
     ((void (*)(__block_impl *))((__block_impl *)myBlock)->FuncPtr)((__block_impl *)myBlock);
     
     return 0;
     }
     static struct IMAGE_INFO { unsigned version; unsigned flag; } _OBJC_IMAGE_INFO = { 0, 2 };
     
     */
    
    Person.h //人类
    #import <Foundation/Foundation.h>
    
    @interface Person : NSObject
    
    @end
    
    Person.m
    #import "Person.h"
    
    @implementation Person
    - (void)dealloc
    {
        NSLog(@"%s",__func__);
        [super dealloc];
    }
    
    @end
    

    相关文章

      网友评论

          本文标题:OC语言day06-15Block注意事项

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