OC学习笔记之blcok

block的基本概念及基本用法
     1.OC比C中多出的几个数据类型
        SEL,id,BLOCK,BOOL,Boolean
     2.BLOCK类型是一个C级别的语法和运行机制
     3.Block的基本用法


block的typedef
    用于给block起别名。 
    1.格式
       typedef 返回值类型 (^新别名) (参数列表名);
       typedef int(^myblock) (int,int);//此时的myblock不再是一个指针变量,而是一个类型,比如int,char。
       例子:
       int main(int argc,const char * argv[]){
            autoreleasepool{
                   void (^myblock)() = ^{
                           NSLog(@"helloworld\n");
                   }
            }
            myblock();
            typedef void (^block)();//定义了blcok类型,无参数无返回值
            block b1;
            b1 = ^{
                 NSLog(@"helloworld");
            }
            typedef int (^newtype1) (int,int);//定义了block类型,有参数有返回值
            newtype nt1 = ^(int a,int b){
                     return a+b;
            }
            int s = nt1(12,23);
            NSLog(@"s = %d",s);
            
       }


block访问外部变量-------面试题
     1.在block内部是否可以访问外部的变量
        (1)block相当于一个对象,在堆区。编译的时候,系统会将外部变量(栈区)copy一份到block所属于堆区。
         int main(int argc, const char * argv[]){
                 int m = 10;
                 NSLog(@"1:m = %d",m);
                 NSLog(@"2:m addr = %p",&m);//地址在栈区
                 void (^myblock)() = ^(){//创建block的时候,会将外部变量辅助一份放在block对象中,也就是在堆区
                        NSLog(@"5:m addr = %p");//地址在堆区
                        NSLog(@"3:in block m = %d");
                 }
                 NSLog(@"4:m addr = %p",&m);//地址栈区
                 myblock();
         }
         打印结果:
          2:m addr = 0x7fff5fbff7bc
          4:m addr = 0x7fff5fbff7bc
          5:m addr = 0x100600180
          注:堆区的后6位一般都有内容,而静态区(常量区)后四位有内容,从后四位往前四位都为0.而栈区的地址方位较长
        (2)copy的时候,是以const的方式copy的方式copy进来的,所以在block内无法修改外部变量值
          int main(int argc, const char * argv[]){
                 int m = 10;
                 NSLog(@"1:m = %d",m);
                 NSLog(@"2:m addr = %p",&m);//地址在栈区
                 void (^myblock)() = ^(){//创建block的时候,会将外部变量辅助一份放在block对象中,也就是在堆区
                        m =10;//编译的时候会报错,因为m是以const的方式copy进来的
                        NSLog(@"5:m addr = %p");//地址在堆区
                        NSLog(@"3:in block m = %d");
                 }
                 NSLog(@"4:m addr = %p",&m);//地址栈区
                 myblock();
         }
        (3)在block内部可以重新定义外部变量,并且该变量也会存放在栈区。
         int main(int argc, const char * argv[]){
                 int m = 10;
                 NSLog(@"1:m = %d",m);
                 NSLog(@"2:m addr = %p",&m);//地址在栈区
                 void (^myblock)() = ^(){//创建block的时候,会将外部变量辅助一份放在block对象中,也就是在堆区
                        int m =100;//该m在栈区,因为创建的是局部变量
                        NSLog(@"5:m addr = %p");//地址在栈区
                        NSLog(@"3:in block m = %d");
                 }
                 NSLog(@"4:m addr = %p",&m);//地址栈区
                 myblock();
         }
        (4)如果必须在block内部修改外部变量的话,可以使用__block修饰变量。此时不再以const的方式copy
         int main(int argc, const char * argv[]){
                 __block int m = 10;//使用block修饰,可以在block中修改m的值
                 NSLog(@"1:m = %d",m);
                 NSLog(@"2:m addr = %p",&m);//地址在栈区
                 void (^myblock)() = ^(){//此处copy的不再以const的方式copy的
                        m =100;//该m在堆区,因为创建的是局部变量
                        NSLog(@"5:m addr = %p");//地址在堆区
                        NSLog(@"3:in block m = %d");
                 }
                 myblock();
                 NSLog(@"4:m addr = %p",&m);//地址堆区,使用const修改的变量在block中被赋值后,之后使用的
                                                                // 该变量都是在堆区中取得。
         }
        

注意:
   1.blcok的分类
      全局block:定义在函数外面的block是global类型的;另外,如果函数内部的block,但是没有捕获任何的自动变
                     量,那么他也是全局的
      栈block:与全局block的区别为是否引用了外部变量(不懂)
      堆bock:堆block则是对栈block copy得来,堆全局block copy不会有任何作用,返回的依然是全局block(不懂)
    2.常量变量
      常量变量(NSString *a = @"helllo";a为变量。@“hello”为常量)-----------不加__block类型的话,block会引用
      常量的地址(浅拷贝)。加上__block类型的话,block回去引用常量变量(如:a是变量,a=@"abc",可以任意修
      改a指向的内容)
      如果不加__block,直接在block内部修改变量,编译会报错。block内部该变量是只读的。


block可以作为函数的返回值
   1.步骤
      (1)使用typedef定义一个新的类型
          typedef void (^newtype)();
      (2)使用新的类型作为函数的返回值
      (3)定义block变量,接收函数返回值的结果
      (4)执行block
      例子:
      typedef void (^newtype)();//使用typedef定义一个新的类型 
      newtype test(){//用新定义的类型作为函数的返回值
           newtype w1 = ^(){
                    NSLog(@"xxxx");
                    NSLog(@"hello wlord");
           }
           return w1;//返回值block
      }
      typedef int (^newtype1)(int ,int );
      newtype test1(){
             return ^(int a,int b){
                  return a+b;
             }
      }
      int main(int argc,const char * argv[]){
           @autoreleasepool{
                   newtype n1 = test();//定义block变量接收函数返回值的结果。
                   n1();//执行函数
                   newtype1 n2 = test1();
                   int s = n2(23,12);
                   NSLog(@"s = %d",s);
           }
           return 0;
      }


block的使用技巧及其注意事项
    1.block助记符
       输入inlineBlock,直接回车。block的格式模板会展现出来,可以按照这种方式修改。
    2.自己写助记符


















  
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值