zoukankan      html  css  js  c++  java
  • iOS多线程_03_Block

      1、block定义

      是准备好的一段代码片段,在需要的时候执行

      注意:block 是C语言的格式

      2、block格式

      格式:返回类型 (^blockName) (参数类型) = ^(形参列表) { 代码实现 };

      提示:如果没有参数,格式可以简化

      格式:返回类型 (^blockName) () = ^ { 代码实现 };

      在Xcode代码编辑中输入 inlineBlock,有提示,这是block格式的快捷方式

      3、示例代码

      (1)先看看block怎么用

        void (^myBlock)() = ^ {
            NSLog(@"hello block");
        };
        
        // 调用block
        myBlock();

      输出结果是:hello block

      (2)带参数

        void (^sumBlock)(int, int) = ^(int x, int y) {
            NSLog(@"%d", x + y);
        };
        
        sumBlock(10, 20);

      输出结果是:30

      (3)block到底干了什么

        int x = 10;
        NSLog(@"%p", &x);
        
        // 在定义block时,如果block中使用到外部的“局部”变量,block会建立该变量的副本(会记录当前x的数值)
        void(^myBlock)() = ^ {
            NSLog(@"%d", x);
            NSLog(@"%p", &x);
        };
        myBlock();

      输出结果:

      0xbfffc8e4

      10

      0x8e632a4

      从地址可以看出block内部的x跟外部的x不是同一个,不过内容都是10

      block的作用:在 NSLog(@"%d", x); 中,因为使用到“局部变量”x,所以myBlock会建立x的副本,在输出 NSLog(@"%d", x);的时候把x的值输出。

      所以,可以得出结论,block里面用到了谁,block就会建立谁的副本,在使用的时候输出它的值。

      4、常见面试题

      (1)在使用外部变量时,默认不允许在块代码中直接修改外部变量的数值

      上边这张图很明显的说明,默认情况下是不允许在块代码中直接修改外部变量的数值的

      (2)如果要修改外部变量的值,需要在定义变量的时候用 __block 修饰

      (3)__block的另一个特点:被__block修饰的变量,在值改变的时候,块代码内会同步被改变后的值

      上面这段代码的输出结果是:

      0xbfffc8e8

      20

      === 0x8cadbb0

      20

      结果表明,在 x = 20; 之后,block内部的x值的副本也改变了

      如果把 __block 去掉,输出结果是:

      0xbfffc8e4

      10

      === 0xa275f74

      20

      注意:在x = 20;之后调用block才会同步20的值,一定不要忘了代码是顺序执行的

      提示:为了保证代码的可读性,通常不使用 __block

      总结:上面介绍的block的用法,block本质上是创建了副本,要注意的是,副本的内容还是变量的内容,而副本在内存中存储的地址变了

      (4)再来看block保存指针变量

     1     // 指针包含指针的地址,和指向的地址
     2     NSMutableString *str = [NSMutableString stringWithString:@"hello"];
     3     NSLog(@"%p %p", &str, str);
     4     
     5     void(^myBlock)() = ^ {
     6         // 修改指针指向内存空间的内容
     7         [str setString:@"world"];
     8         NSLog(@"%p %p", &str, str);
     9         NSLog(@"%@", str);
    10     };
    11     
    12     myBlock();
    13     NSLog(@"%p %p", &str, str);
    14     NSLog(@"%@", str);

      输出结果是:

      0xbfffc8e4 0x8c281f0

      0x8d0b834 0x8c281f0

      world

      0xbfffc8e4 0x8c281f0

      world

    这幅图并不准确,block保存的副本具体在哪儿存着,我也不是太清楚,因为从地址观察,block副本很可能不是在栈中,不过,有一点确定的是,block肯定建立了一个副本。可以将block当做特殊的对象。

      第3行代码,分别输出了栈中指针str的地址和堆中对象hello的地址。

      第5行代码,block建立了str的副本指针,内容不变,地址变了;然后第7行代码修改了block中str指向的对象的内容,因此堆中对象的内容变为world。

      第13行代码,可以说明,指针str的地址和指向的地址都没有变。

      第14行代码,输出了str指针指向的对象内容。

  • 相关阅读:
    wpf动态增加删除控件
    写了个批量查询qs的软件
    wcf感悟与问题
    asp.net发布到IIS中出现错误:处理程序“PageHandlerFactory-Integrated”在其模块列表中有一个错误模块“ManagedPipelineHandler”
    数据结构实验之二叉树的建立与遍历
    数据结构实验之二叉树八:(中序后序)求二叉树的深度
    数据结构实验之二叉树七:叶子问题
    数据结构实验之二叉树四:(先序中序)还原二叉树
    数据结构实验之二叉树三:统计叶子数
    数据结构实验之求二叉树后序遍历和层次遍历
  • 原文地址:https://www.cnblogs.com/yudigege/p/3930408.html
Copyright © 2011-2022 走看看