iOS 之 (闭包)block传值

在iOSAPP开发的过程中 我们会用到很多需要传值的地方 传值的方式也多种多样 有:代理传值、通知传值、KVC、KVO、block、单例 等。其中block 因为其简洁实用规范的代码 无疑是大牛们传值的不二选择 但对于初学者来说要理解并能运用 起初确实有些难以理解 以下我将细细的介绍下block 

首先我总结了一下block的公式:

步骤 1.block 的声明   返回值类型(^block 的名字)(参数列表);

    步骤 2.block 实现   block的名字 = ^(参数列表)(){};

    步骤 3.block 的调用   block的名字();

下面是一个简单的block

//    声明
    void(^blockName)(int num,NSString *string);
//    实现
    blockName = ^(int num,NSString *string)
    {
        NSLog(@"%d,%@",num,string);
    };
//    调用
    blockName(520,@"phyone_");
}
由该例可以看出block的代码执行顺序和其他的代码执行顺序不一样 它是先执行声明代码 然后执行调用代码 最后才执行实现代码 由此我们利用block的回调性质 达到我们传值效果 当然这只是在一个页面的一段代码 只是说明了它具有传值的作用 下面我们来试试 多页面之间的block反向传值 由于是反向传值 所以我们创建两个ViewController ( ViewController,Next_ViewController)先由 ViewController跳到Next_ViewController里将里面的值反向传给ViewController 

以下是代码

ViewController.m里面

- (void)viewDidLoad {
    [super viewDidLoad];
    self.view.backgroundColor = [UIColor purpleColor];
 UILabel *lable = [[UILabel alloc]initWithFrame:CGRectMake(100, 200, 200, 100)];
    lable.backgroundColor = [UIColor brownColor];
    [self.view addSubview:lable];
    
    UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc]initWithTarget:self action:@selector(tap)];
    [self.view addGestureRecognizer:tap];
}

- (void)tap
{
    Next_ViewController *NVC = [[Next_ViewController alloc]init];
    NVC.block = ^(NSString *content){
        NSLog(@"%@",content);
        UIButton *button = [[UIButton alloc]initWithFrame:CGRectMake(100, 200, 100, 100)];
        [button setTitle:content forState:UIControlStateNormal];
        button.backgroundColor = [UIColor orangeColor];
        [self.view addSubview:button];
    };
    [self presentViewController:NVC animated:YES completion:nil];
}

Next_ ViewController.h里面

//block 是分配在栈里面的用copy
@property(nonatomic,copy) void(^block)(NSString *content);

Next_ViewController.m里面

全局变量
<p style="margin-top: 0px; margin-bottom: 0px; font-family: Menlo;"><span style="font-size:12px;">{</span></p><p style="margin-top: 0px; margin-bottom: 0px; font-family: Menlo;"><span style="font-size:12px;">    void(^imageNameBlock_1)(NSString *imageName);</span></p><p style="margin-top: 0px; margin-bottom: 0px; font-family: Menlo;"><span style="font-size:12px;">    void(^lableBlock)(NSString *tontentText);</span></p><p style="margin-top: 0px; margin-bottom: 0px; font-family: Menlo;"><span style="font-size:12px;">}</span></p>
- (void)viewDidLoad {
    [super viewDidLoad];
    self.view.backgroundColor = [UIColor orangeColor];
    UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
    button.frame = CGRectMake(100, 200, 100, 50);
    [button setTitle:@"123456" forState:UIControlStateNormal];
    button.backgroundColor = [UIColor redColor];
    [button addTarget:self action:@selector(buttonAction:) forControlEvents:UIControlEventTouchUpInside];
    [self.view addSubview:button];
}

- (void)buttonAction:(UIButton *)sender
{
//    点击按钮 返回上一个页面 同时通过block 把这个值传到上一个页面
    self.block(sender.titleLabel.text);
    [self dismissViewControllerAnimated:nil completion:nil];
}

另外:block 还有两个问题

1.怎么改变block里面的值

用上面的代码 在ViewController.m viewDidLoad 里面 添加代码

 1.局部变量
 定义一个图片名字的Block
 */
//    局部变量
    
    void(^imageNameBlock)(NSString *imageName);
//    如果想修改Block里面的值 需添加__block修饰
    
//    __block UIImage *image;
    imageNameBlock = ^(NSString *imageName)
    {
        image = [UIImage imageNamed:imageName];
        self.view.backgroundColor = [UIColor colorWithPatternImage:image];
    };
    imageNameBlock(@"17.jpg");
就会出现 Use of undeclared identifier 'image' 错误情况 原因是我们试图改变block里面的值 解决办法就是 添加 __block 修饰(解注释

__block UIImage *image;) 就行了


2.block的循环引用

用上面的代码 在ViewController.m viewDidLoad 里面 添加代码

//    全局变量
//    block循环 引用 解决  我们用弱引用 __block
    __weak ViewController *VC = self;
    
    __block UIImage *image = nil;
    imageNameBlock_1 = ^(NSString *imageName)
    {
        image = [UIImage imageNamed:imageName];
        VC.view.backgroundColor = [UIColor colorWithPatternImage:image];
    };
    
    UILabel *lable = [[UILabel alloc]initWithFrame:CGRectMake(100, 200, 200, 100)];
    lable.backgroundColor = [UIColor brownColor];
    [self.view addSubview:lable];
    
    UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc]initWithTarget:self action:@selector(tap)];
    [self.view addGestureRecognizer:tap];

再添加两个方法

- (void)loadData
{
    imageNameBlock_1(@"17.jpg");
}

- (void)viewWillAppear:(BOOL)animated
{
    [self loadData];
}

当出现循环引用是我们用__weak修饰下 但具体机制还不太懂 希望高人指点



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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值