美文网首页
块(Blocks)

块(Blocks)

作者: ssdfsj | 来源:发表于2015-12-21 21:09 被阅读54次

    《Objective-C程序设计第四版中文翻译》对Blocks介绍得有点少,对block还是糊里糊涂的,真用到的时候有点迷惘。

    块是对C语言的一种扩展,优势:能让系统分配给其他处理器或者应用的其他线程执行,通常用于配合GCD写多线程。看起来像函数 ,跟函数相同之处:可以像函数一样给它传值,接收返回值;不同之处:块定义在函数或者方法内部,能访问在函数或者方法范围内块之外的任何变量。访问只能读取变量的值,如果需要改变,要在定义块的时候使用块修改器声明。

    块是以插入字符“^”开头为标识的,下面是块的定义和调用。

    void (^print_message)(void) =

    ^(void) {

    NSLog(@"Programming is fun.");

    }; //定义

    print_message();//调用

    但是一般你看到的是这样,没有名字的块,只有传入的参数和块内的具体代码。

    [reader setCompletionWithBlock:^(NSString *resultAsString) {

            webUrl = resultAsString;

            [self ReadyToDownload];

           [wSelf.navigationController popViewControllerAnimated:YES];

       }];

    如果在定义变量的时候使用__block , 如 __block int n = 1;则说明这个变量能在代码块内被改变。

    但是我还是不懂这个block,那就参考唐巧大牛的博客来做点练习,看能不能自己理解。

    1.isa指针,跟对象一样,都有isa指针,用于指向变量或者对象存储的内存地址。

    2.flags,用于按 bit 位表示一些 block 的附加信息。

    3.reserved,保留变量。

    4.invoke,函数指针,指向具体的 block 实现的函数调用地址。

    5.descriptor, 表示该 block 的附加描述信息,主要是 size 大小,以及 copy 和 dispose 函数的指针。

    6.variables,capture 过来的变量,block 能够访问它外部的局部变量,就是因为将这些变量(或变量的地址)复制到了结构体中。

    关于存储位置:在Objective-C语言中,一共有3种类型的block:

    (1)_NSConcreteGlobalBlock 全局的静态block,不会访问任何外部变量。

    (2)_NSConcreteStackBlock 保存在栈中的block,当函数返回时会被销毁。

     (3)_NSConcreteMallocBlock 保存在堆中的block,当引用计数为0时会被销毁。

    参考block的例题说明:

    Example B

    void exampleB_addBlockToArray(NSMutableArray *array) {

    char b = 'B';

    [array addObject:^{

    printf("%cn", b);

    }];

    }

    void exampleB() {

    NSMutableArray *array = [NSMutableArray array];

    exampleB_addBlockToArray(array);

    void (^block)() = [array objectAtIndex:0];

    block();

    }

    在MRC的时候,block是_NSConcreteStackBlock类型,被创建保存在栈中,一旦所在函数返回,则会被摧毁。所以exampleB_addBlockToArray(array);运行完之后,存在栈上面的变量b就不存在了。

    如果把函数改为

    void exampleB_addBlockToArray(NSMutableArray *array) {

    [array addObject:^{

    printf("cn");

    }];

    }

    这样的话,block是_NSConcreteGlobalBlock,全局的静态block,不会访问任何外部变量。不用考虑内存问题。

    Example D

    typedef void (^dBlock)();

    dBlock exampleD_getBlock() {

    char d = 'D';

    return ^{

    printf("%cn", d);

    };

    }

    void exampleD() {

    exampleD_getBlock()();

    }

    这个也是一样,把block返回,但是里面的变量在没有ARC的情况下是函数返回就被销毁的。这个跟函数一样的,那关于传入参数的问题,应该也是一样的。

    总结:这样看来,block像一个能运行代码的对象,里面的变量就像在函数里一样,局部变量会在返回的时候被销毁,需要像Example B和D那样使用block,需要ARC,它把所有对象的放在堆上面,包括block,方便管理。而在block里访问block外的变量的话,只是把值copy进block内,需要加上__block关键字,才能把变量地址传进block,在block内进行修改。

    参考:谈Objective-C Block的实现-唐巧  , Objective-C Blocks Quiz

    相关文章

      网友评论

          本文标题:块(Blocks)

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