IOS中 Block用法进阶三 关于存储变量和应用举例

一、存储变量本质分析

先看下面这段代码和运行结果。

    int number=100;
    int (^testBlock)(int)=^(int x){
        return number+x;
    };
    NSLog(@"调用block的结果为:%d",testBlock(100));
    number=200;
    NSLog(@"改变number的值后,再次调用block的结果为:%d",testBlock(100));

分析:第一次调用block块的时候 x为100 number也是100  应该输出200   看运行结果:

2016-05-25 09:42:29.805 NewStyle[738:19498] 调用block的结果为:200

那么接下来,我们改变了number的值,再次调用block的时候 x仍为100,number为200,那么结果会不会是300呢?看运行结果如下:

2016-05-25 09:42:29.806 NewStyle[738:19498] 改变number的值后,再次调用block的结果为:200

结论: 为什么结果是200 ?而不是300 呢?那会不会是block记录了第一次number的值,后面修改不起作用呢???如果是个指针会是什么样子的呢?看下面代码:

    int a=2;
    int *p=&a;//p指针指向值为2的变量a的地址
    int (^testBlock2)(int)=^(int y){
        return *p+y;
    };
    NSLog(@"调用block的结果为:%d",testBlock2(2));//4
    NSLog(@"p指针取值:%d   变量a的值:%d ",*p,a);//2  2
    *p=4;
    NSLog(@"改变指针p对应的值以后再次调用block的结果为:%d",testBlock2(2));//6
    NSLog(@"修改指针p对应的值以后,p指针取值:%d   变量a的值:%d",*p,a);//4 4
我们定义一个普通局部变量a并初始化为2,接下来定义一个指针p指向a。毫无疑问,p指针指向地址的值为2。那么此时运行如下

2016-05-25 09:58:15.757 NewStyle[769:26498] 调用block的结果为:4

2016-05-25 09:58:15.757 NewStyle[769:26498] p指针取值:2   变量a的值:2

当我们通过p指针修改其所指地址的值时,这里修改p指针所指内容为4。运行效果如下:

2016-05-25 09:58:15.757 NewStyle[769:26498] 修改指针p对应的值以后,p指针取值:4   变量a的值:4

结论: testBlock 在其主体中用到的 number 这个变量值的时候做了一个 copy 的动作,把 number 的值 copy 下来。所以,之后 number 即使换成了新的值,对于 testBlock 里面 copy 的值是没有影响的。需要注意的是,这里copy的值是变量的值,如果它是一个记忆体的位置(地址),换句话说,如果这个变量是个指针的话,那么此时对testBlock里面copy的值是有影响的。那么在block里面可不可以通过修改指针的值呢?看看如下代码:
    int b=10;
    int *pointer=&b;
    int (^testBlock3)(int)=^(int z){
        *pointer=20;//我们前面提到普通局部变量(非指针)在block里面如果不加__block修饰 是不可以修改的 会报编译错误。这里貌似没有报编译错误,
        return *pointer+z;
    };
    NSLog(@"看看结果 %d",testBlock3(10));//30?

这里定义了一个指针,  并指向了局部变量b。那么此时指针pointer所指的地址的值就是变量b的值,毫无疑问就是10。接下来在block块里面我们通过指针修改了pointer指针的值。运行结果如下:

2016-05-25 09:58:15.756 NewStyle[769:26498] 看看结果 30

结论,指针型变量在block里面可以修改。


二、Block高级应用举例——两个控制器之间的传值

那么,我这里有两个控制器 ViewController和myTestVC 通过在ViewController里面点击一个按钮触发事件推出控制器myTestVC。
ViewController里面的代码如下:

//按钮触发事件 推出控制器myTestVC
-(void)btnClicked:(UIButton *)Sender{
    myTestVC *vc =[[myTestVC alloc]init];
    //这里会回调
    vc.responseStr = ^(NSString *str){
        UIAlertView *alertView=[[UIAlertView alloc] initWithTitle:@"Block高级应用" message:str delegate:nil cancelButtonTitle:@"确定" otherButtonTitles:nil,nil];
        [alertView show];
    };
    [self.navigationController pushViewController:vc animated:YES];
}
在myTestVC.h中申明如下block。

/**
 *  定义了一个response的Block。这个response必须带一个参数,这个参数的类型必须为id类型的
 *  无返回值
 *  @param id
 */
typedef void(^response)(id);

@interface myTestVC : RootViewController

/**
 *  用上面定义的response声明一个Block,声明的这个Block必须遵守声明的要求。
 */
@property (nonatomic, copy) response responseStr;

@end

在myTestVC.m中,在即将返回上一层视图控制器(这里指返回ViewController喽)的事件中,添加如下代码:

//返回上一层控制器事件
-(void)leftTextItemClicked:(UIBarButtonItem*)item{
    //you should override this method when you use it in a subclass of RootViewController.
    //声明一个字符串
    NSString *responseString = @"我们回来啦!我们回来啦!";
    //用刚刚声明的那个Block去应答 并传递到上一个VC 这里肯定是ViewController啦
    self.responseStr(responseString);
    [self.navigationController popViewControllerAnimated:YES];//返回到上一层视图控制器
}

运行下,看看效果如何。



至此,Block的基本用法差不多就这些喽,后面继续分享其他有趣的知识。












  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值