block一 : block的基本语法和使用

1.block的语法:

block定义的标准方法为:

^返回值类型 (参数列表) {表达式

例如:

^ int (void) {
        return 1;
    };

其中int是返回值类型。void是参数列表,表示不传参数。{}中的是表达式。

但是当一些情况下,有的参数是可以省略的。下面就说一下这些省略的情况

①. 当返回值类型是void的时候,void可以省略

例如:

^ void (void) {
        NSLog(@"这是block");
    };
^ (void) {
        NSLog(@"这是block");
    };
这两个表达式是一样的。


②.当参数是void的时候,参数也是可以省略的。例如:

^ (void) {
        NSLog(@"这是block");
    };
^{
        NSLog(@"这是block");
    };
这两个表达式也是一样的。


2. block的申明

有的时候当block定义之前需要申明。下面我们来看看block申明的方法:

返回值类型 (^block的名字) (参数列表

例如:

int (^block)(int) =  ^ int (int a){
        return a+1;
    };

等号前面的就是block的申明。申明的block必须和赋值的block一致,否则会出现编译错误


3. block的使用

①block当成变量使用

block其实也是一种变量,可以把他当成一个变量使用,最常用的方法是在文件头先定义一个block。用申明的方法定义。例如:

typedef int (^block) (int);
定义过之后就可以和使用变量一样,用block的名字使用定义的这个block了,例:

block selfBlock = ^ int (int a){
        return a+1;
    };
int (^block)(int) =  ^ int (int a){
        return a+1;
    };
这两段代码是一样的。
前面一个是直接像使用变量一样使用block,类似int a =... 这里就用 block a =...。

②block截取自动变量和改变外部变量值

block具有截取自动变量的功能。例:

{  
    int m=0;
    int (^block)(void) =  ^ int {
        NSLog(@"in block m=%d",m);
        return 1;
    };
    m = 3;
    block();
}
输出:in block m=0
截取自动变量就是在block定义的时候,将外部变量截取,在block中这个变量值不再改变。如例所示,在定义block的时候已经将变量截取了。所以在block中,m=0。不会因为外部m改变而改变。所以输出的是0,不是3。

实际他的具体实现是因为创建block的时候有一个赋值操作,将外部变量进行了复制。

{
    int m=0;
    int (^block)(void) =  ^ int {
        int inblock = m;
        NSLog(@"in block m=%d",inblock);
        return 1;
    };
    m = 3;
    block();

}
block的具体实现类似上面这段代码,block会自带一个变量inblock。在block创建的时候会用这个变量保存外部变量m,block内部使用到m的地方,都会用inblock代替。所以当外部的m改变时,和block内部m的使用已经完全没关系了。


普通情况下是不能在block中改变外部变量的值的,如上面所说,因为block内部的外部变量都是赋值来的,所以是无法改变的,如果直接在内部写上改变值的代码,在编译的时候,会报编译错误。如图所示。



如果真的想改变变量的值,可以在定义变量的时候使用__block。

{
    __block int m=0;
    int (^block)(void) =  ^ int {
        m = 1;
        NSLog(@"in block m=%d",m);
        return 1;
    };
    m = 3;
    block();
}
这样就不会报编译错误了。但是注意了,加上 __block的变量将不会拥有截取自动变量的功能。原理上来说,加上__block之后,block内部的inblock将不会赋值,而是直接使用外部变量。不会具有截取自动变量功能。我们来用例子看看。
{
    __block int m=0;
    int (^block)(void) =  ^ int {
        NSLog(@"in block m=%d",m);
        return 1;
    };
    m = 3;
    block();
}
输出:in block m=3
使用上面截取自动变量的例子。在变量定义时候加上 __block。输出完全变了。block将不再拥有截取自动变量的功能

4.Block使用copy

每个block都会有自己的作用域,在超出作用域的时候,有时不使用copy的话,会导致崩溃,特别是非ARC的情况下,下面我们来看看什么时候不需要copy,什么时候需要copy

①在未使用外部变量的情况下,block属于全局变量,不需要copy

        bbk = ^{
            NSLog(@"abcde");
        };
②.其他情况下,除了使用GCD之外,都最好使用copy,否则就会有崩溃的风险




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值