iOS开发之block(一)

本文将介绍一下iOS开发中的用到的新语法:block

首先来看看block变量的定义和使用

- (void)testBlock {

   

   /********************无参数、无返回值的block********************/

   // 1.定义一个无参数无返回值的block变量

   void (^block1)() = ^() {

       NSLog(@"this is a block");

   };

   // 2.使用该block

   block1();// 打印:this is ablock

   

   

   

   /********************有参数、有返回值的block********************/

   // 1.定义一个无参数无返回值的block变量

   int (^block2)(int, NSString *) = ^(int age, NSString *name) {\

       NSLog(@"name = %@", name);

       return 20;

   };

   // 2.使用该block

   int number = block2(20, @"jack");// 打印:name = jack

   NSLog(@"%d", number);// 打印:20

   

   

   /********************方法外的block********************/

   block();// 打印:out function

}

 

void (^block)() = ^(){

   NSLog(@"out function");

};

其他情况的block就不一一举例了。这上面的例子可以看出定义block变量,就相当于定义了一个函数。但是区别也很明显,因为函数肯定是在方法外面定义,而block变量定义在了方法内部。当然,我们也可以把block定义在方法外部,例如上面的代码块block的定义,就在-(void)testBlock外面。

可以看出在定义block的地方,并不会执行block{}内部的代码,而在block调用之后才会执行其中的代码,这跟函数的理解其实差不多。即只有在调用block(函数)的时候才会执行block体内(函数体内)的代码

block作用:存储代码,等到调用它的时候再执行

__block关键字的使用

在block的{}体内,是不可以对外面的变量进行更改的。


编译直接报错。如果我们就是需要在block中修改变量的值,这个时候怎么办呢?我们可以使用__block关键字来定义该变量。利用__block定义的变量是可以在block中修改该变量的值的

- (void)testBlock {

    __block int number = 10;// 使用__block定义变量 

   // 定义一个block修改变量number的值:number + 1

   int (^myBlock)(int) = ^(int a) {

       number = number + a;

       return number;

   };   

   // 调用block

   int result = myBlock(10);

   NSLog(@"result = %d", result);// 打印:20
}

block类型

现在我们学会如何定义、使用block了。那么看看下面这个例子

- (void)testBlock {

   void (^block1)() = ^() {

       int num = 10 + 20;

       NSLog(@"block1 - %d", num);

   };
   void (^block2)() = ^() {

       int num = 10 - 20;

       NSLog(@"block2 - %d", num);

   };

   void (^block3)() = ^() {

       int num = 10 * 20;

       NSLog(@"block3 - %d", num);

   };

   void (^block4)() = ^() {

       int num = 10 / 20;

       NSLog(@"block4 - %d", num);

   };

   

   block1();// 打印:block1 – 30

   block2();// 打印:block2 – -10

   block3();// 打印:block3 – 200

   block4();// 打印:block4 – 0
}


以上4个block都是没有返回值,也没有参数,即4个block属于同一个类型。如果每次定义这样的block有没有觉得好麻烦。其实在OC中我们可以使用关键字来定义这种类型。

我们先从简单的定义类型:

typedef int MyInt;

- (void)test {

   MyInt a = 10;

   NSLog(@"a = %d", a);

}

上面我们使用了typedef给int类型起了一个别名MyInt,这样int能使用的地方,MyInt也能使用。其实block类型也是一样的。如下:(和定义整型对比看)

所以上面加减乘除的例子可以如下:

typedef void (^BlockType)();
- (void)testBlock {
    BlockType blockSum = ^() {
        int num = 10 + 20;
        NSLog(@"block4 - %d", num);
    };
    BlockType blockSub = ^() {
        int num = 10 - 20;
        NSLog(@"block4 - %d", num);
    };
    BlockType blockMul = ^() {
        int num = 10 * 20;
        NSLog(@"block4 - %d", num);
    };
    BlockType blockDivide = ^() {
        int num = 10 / 20;
        NSLog(@"block4 - %d", num);
    };
    
    blockSum();// 打印:block1 – 30
    blockSub();// 打印:block2 - -10
    blockMul();// 打印:block3 – 200
    blockDivide();// 打印:block4 – 0
}

是不是简单了呢。

block作为对象属性

block作为对象的属性可以存储该对象想要做的一些操作。当调用该对象的时候,对象的block就执行这些操作。

看下面的例子:

新建一个HXPerson类,当点击控制器view的时候,就让对象执行之前存储在block中的操作。

HXPerson.h

#import <Foundation/Foundation.h>

typedef void (^BlockType)();

@interface HXPerson : NSObject
@property (nonatomic, copy) BlockType printSomething;// block类型属性
@end

HXPerson.m文件中什么都没写,我们主要看block的功能。

现在控制器中使用HXPerson类。

- (void)viewDidLoad {
    [super viewDidLoad];
    
    HXPerson *person = [[HXPerson alloc] init];
    person.age = 20;
    // 定义person对象的block属性(先让person的block存储一些操作)
    person.printSomething = ^(){
        NSLog(@"person");
    };
    self.person = person;
}
/**
 *  当点击控制器view的时候,就让person执行之前存储在block中的操作。
 */
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
		// 调用person的block
    self.person.printSomething();
}
运行结果:

block传值

利用block可以存储操作的这个特点,我们还可以使用block进行页面之间的传值,之前已经介绍过两种数据传递的方法,今天介绍第三种数据传递的方法:block传值

例子:两个控制器A、B,现在要将B中的数据传递给A

首先创建两个控制器:

要想把NextViewController的数据传递出来,就要在该控制器中定义block来传递

NextViewController.h

#import <UIKit/UIKit.h>

typedef void (^MyBlock)(NSString *text);

@interface NextViewController : UIViewController

@property (nonatomic, copy) MyBlock block;

@end

点击ViewController上的按钮,跳转到NextViewController。跳转前在NextViewController的block属性 中存储操作。

ViewController.m

- (IBAction)next {
    // 从storyboard中加载控制器(之前介绍过控制器的创建)
    UIStoryboard *st = [UIStoryboard storyboardWithName:@"Main" bundle:nil];
    NextViewController *vc = [st instantiateViewControllerWithIdentifier:@"next"];
    // 在跳转的时候,先在block属性中存储操作(将传过来的字符串,赋值给label)
    vc.block = ^(NSString *text){
        self.label.text = text;
    };
    
    [self presentViewController:vc animated:YES completion:nil];
}

跳转到NextViewController控制器。

NextViewController.m

- (IBAction)previous {
    
    // 在返回上一页面的时候,调用block,执行之前存储的操作
    if (self.block) {
        self.block(self.textField.text);
    }
    
    [self dismissViewControllerAnimated:YES completion:nil];
}
运行结果:

block传递只能逆传。不能顺传。即如果A跳转到B,则使用block只能将B的数据传递的A。

之后的文章将介绍关于block的内存管理问题。



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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值