iOS Block的简单使用

1.简介
  • block是代码块,其本质和变量类似。不同的是代码块存储的数据是一个函数体。使用Block,就可以像其他标准函数一样,传入参数,并得到返回值。
  • block是一种比较特殊的数据类型,我们可以把Block当作是Object-C的一种匿名函数。常见的场景有:界面传值,带代码进行封装作为参数传递等。
  • block分为三种类型
    1、 NSConcreteStackBlock ,存储在栈上,在block内部引用外部变量,在函数退出的时候,block所占的内存空间会被回收;
    2、NSConcreteGlobalBlock,类似函数,存储在程序的数据区域(text段),在block内部没有引用任何外部变量;
    3、NSConcreteMallocBlock,存储在堆上,一般是对NSConcreteStackBlock进行copy操作获取。
2.定义和使用
a.定义
    返回值(^ block变量)(形参列表) = ^(实参列表) {
        行为主体
    };
b.使用
b-1.无返回值无参数
    void(^block)() = ^(){
        NSLog(@"这是一个无返回值无参数的block");
    };
    block();
b-2.有返回值无参数
    NSString *(^block)() = ^() {
        return @"这是一个有返回值无参数的block";
    };

    NSLog(@"%@",block());
b-3.无返回值有参数
    void(^block)(int) = ^(int x) {
        NSLog(@"这是一个无返回值有参数的block,x=%d",x);
    };
    block(10);
b-4.有返回值有参数
    int (^block)(int) = ^(int x) {
        NSLog(@"这是一个有返回值有参数的block");
        return x*2;
    };
    int y = block(10);
    NSLog(@"x*2===%d",y);
3.__block关键字的使用

在block的代码块(行为主体)中,我们是不能直接修改外面定义好的变量的。如下代码所示:

    int a = 5;
    int (^block)(int) = ^(int x) {
        x = x * a;
        return x;
    };
    a += 5;
    NSLog(@"===%d,===%d",a,block(10));

以上代码输入结果:===10,===50

  • 原因
    block分配的位置默认是栈上分配,在执行的时候会把变量内容拷贝到自己的栈内存上,以便执行的时候可以调用,就以上例子来看,当block去拷贝变量的时候发现 a是一个常量,所以回去引用a的指针,但是它对变量的内容并不是做深拷贝,所以不会去重新申请内存。

  • 解决方案
    在block使用中,但我们需要改变block内部能够读取外部局部变量的值时,我们需要给这个值附加上__block修饰符。将以上代码修改成:

    __block int a =5;
    int (^block)(int) = ^(int x) {
        x = x * a;
        return x;
    };
    a += 5;
    NSLog(@"===%d,===%d",a,block(10));

以上代码输入结果:===10,===100

4.block循环引用

循环引用指的是两个对象互相强引用了对方,从而导致谁也释放不了谁的内存泄漏。
会出现的原因:某个类将block作为自己的属性变量,然后该类在block的方法体里面又使用了该类本身。
解决方案:
__weak typeof (self) weakSelf = self;
__weak someClass *weakSelf = self;

5.block中界面间传值的使用
  • 思路:
    1.创建两个视图FirstViewController和SecondViewController。
    在FirstViewController视图中添加一个UIButton和一个UILable,UIButton的点击事件为跳转(push)到视图SecondViewController。
    在SecondViewController视图中也添加一个UIButton和一个UITextField,UIButton的点击事件为跳转(pop)回视图FirstViewController。
    2.实现的效果:当从SecondViewController视图跳回FirstViewController视图时,让FirstViewController中的UILabel显示SecondViewController的UITextField中的文字。
  • 实现代码
//SecondViewController.h
#import <UIKit/UIKit.h>
typedef void(^textBlock)(NSString *text);  //方式一
@interface SecondViewController : UIViewController
@property (nonatomic, copy) textBlock block;//方式一
@property (nonatomic,copy) void(^colorBlock)(UIColor *color);//方式二
@end
//SecondViewController.m
#import "SecondViewController.h"

@interface SecondViewController ()
@property (weak, nonatomic) IBOutlet UITextField *textFiled;//xib实现
@end

@implementation SecondViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    // 由于是用xib做的视图,这里什么也不需要实现,主要看点击事件
}

- (IBAction)btnClick:(id)sender {
    self.block(self.textFiled.text);//看这里,将textFiled上文字传递回去
    self.colorBlock(self.view.backgroundColor);//看这里,将背景颜色传递回去
    [self.navigationController popViewControllerAnimated:YES];
}
@end

FirstViewController.h中没有实现什么,所以此处就不贴FirstViewController.h的代码了。

//FirstViewController.m
#import "FirstViewController.h"
#import "SecondViewController.h"
@interface FirstViewController ()
@property (weak, nonatomic) IBOutlet UILabel *label;

@end

@implementation FirstViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    // 由于是用xib做的视图,这里什么也不需要实现,主要看点击事件
}

- (IBAction)btnClick:(id)sender {
    SecondViewController *vc = [[SecondViewController alloc] init];

    vc.block = ^(NSString *text) {
        self.label.text = text;
    };

    vc.colorBlock = ^(UIColor *color){
        self.label.backgroundColor = color;
    };

    [self.navigationController pushViewController:vc animated:YES];
}
@end
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值