八天学会OC

第06天OC语言(15):Block注意事项

2017-07-22  本文已影响7人  liyuhong
须读:看完该文章你能做什么?

1.了解block的底层原理
2.什么是____strong__
什么是____weak__
3.什么时候使用__block

学习前:你必须会什么?(在这里我已经默认你具备C语言的基础了)

1.block的使用


一、本章笔记
一、
1.block中可以访问外面的变量
2.block中可以定义和外界同名的变量, 并且如果在block定义了和外界同名的变量,在block中访问的是block中的变量
3.默认情况下,不可以在block中修改外界变量的值
4.不默认情况下,加上__block 修饰符 可以在block中修改外界变量的值
二、
1.验证为什么不加 __block 不能在block中修改外界变量的值
2.验证而加了 __block 就可以在block中修改外界变量的值
  >步骤
    1.通过Clang指令来获取系统编译的C++代码
    2.1.cd到指定文件路径 ,然后通过cc -rewrite-objc main.m
    3.获取.cpp文件.跳到最后的104800行左右找到main.m函数
    找到对应的代码 进行对比(一个是值传递,一个是地址传递)
三、
  block是存储在堆中(copy情况下) 还是栈中(默认情况下)
  如果在block 中访问了外界的对象,一定要给对象加上 __block, 只要加上了 __block 哪怕block在堆中,也不会对外界的兑现进行retain操作
二、code
main.m
#pragma mark 15-Block注意事项
#pragma mark 概念

#pragma mark - 代码
#import <Foundation/Foundation.h>
#pragma mark 类
#import "Person.h"
#pragma mark - main函数
int main(int argc, const char * argv[])
{
#pragma 1.block中可以访问外面的变量
    /*
    int a = 10;
    void (^myBlock)() = ^{
        NSLog(@"a = %i",a);
    };
    myBlock();
     */
#pragma 2.block中可以定义和外界同名的变量, 并且如果在block定义了和外界同名的变量,在block中访问的是block中的变量
    /*
    int a = 10;
    void (^myBlock)() = ^{
        int a = 20;
        NSLog(@"a = %i",a);
    };
    myBlock();
     */
#pragma 3.默认情况下,不可以在block中修改外界变量的值
    
    // 因为block中的变量 和外界的变量 并不是同一个变量
    // 如果block中 访问到了外界的变量,block会将外界的变量拷贝一份到 堆 内存中
    // 因为 block中 使用外界变量是copy, 所以在调用之前修改外界变量的值,不会影响到block中copy的值
    /*
    int a = 10;
    NSLog(@"%p",&a); // 0x7fff5fbff7bc
    void (^myBlock)() = ^{
//        a = 20; // varable is assginable(missing __block type specifier)
        NSLog(@"a = %i",a); // 10
        NSLog(@"%p",&a); // 0x103000160
    };
    a = 20;
    myBlock();
     */
    
#pragma 4.不默认情况下,不可以在block中修改外界变量的值
    // 如果想在block中修改外界变量的值,必须在外界变量 前面加上 __block
    // 如果在block中修改了外界变量的值, 会影响到外界变量的值
    /*
    __block int a = 10;
    NSLog(@"%p",&a);
    void (^myBlock)() = ^{
        a = 33;
        NSLog(@"a = %i",a);
        NSLog(@"%p",&a);
    };
    myBlock();
    NSLog(@"a = %i",a);
    */
#pragma 5.为什么不加 __block 不能在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_c2811e_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; 如果没有添加 __block是值传递
     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 };

     
     // __main_block_impl_0 应该是一个结构体
     // void (*myBlock)() = &__main_block_impl_0(__main_block_func_0, &__main_block_desc_0_DATA, a)) 其中a 是一个值传递
     */
#pragma code
    /*
    int a = 10;
    void (^myBlock)() = ^{
//        a = 10;
        NSLog(@"a = %i",a);
    };
    myBlock();
     */
    
#pragma 6.为什么加 __block 就可在block中修改外界变量的值
    /*
     a = 10; 如果 加上 __block之后就是地址传递,就可在block中修改外界变量的值
     void (*myBlock)() = &__main_block_impl_0(__main_block_func_0, &__main_block_desc_0_DATA, (__Block_byref_a_0 *)&a, 570425344));
     */
    /*
    __block int a = 10;
    void (^myBlock)() = ^{
        a = 13;
        NSLog(@"a2 = %i",a);
    };
    NSLog(@"a1 = %i",a);
    myBlock();
    NSLog(@"a3 = %i",a);
     */
#pragma 7.面试 -- block是存储在堆中(copy情况下) 还是栈中(默认情况下)
    // 默认情况下 block存储在栈中,如果对block进行copy操作,block会转移到堆中
    // 如果block在堆中, block访问了外界的对象,那么会对外界的对象进行retain
    
    // 如果在block 中访问了外界的对象,一定要给对象加上 __block, 只要加上了 __block 哪怕block在堆中,也不会对外界的兑现进行retain操作
//    Person *p = [[Person alloc]init];
    __block Person *p = [[Person alloc]init];
    NSLog(@"retainCount = %lu",[p retainCount]);
    void (^myBlock)() = ^{
        NSLog(@"p = %@",p);
        NSLog(@"retainCount = %lu",[p retainCount]);
    };
    Block_copy(myBlock);
    myBlock();
    
    [p release];
    
    
    return 0;
}

Person
>>>.h
#import <Foundation/Foundation.h>

@interface Person : NSObject

@end

>>>.m
#import "Person.h"

@implementation Person
- (void)dealloc
{
     NSLog(@"%s",__func__);
    [super dealloc];
}
@end


一、获取cpp文件

image.png

通过-rewrite-objc指令

image.png image.png

转成cpp文件

image.png

cpp文件代码

image.png image.png
上一篇 下一篇

猜你喜欢

热点阅读