iOS开发-block的使用(上)

2017-01-09  本文已影响30人  心猿意码

引言:本文旨在介绍block的基本用法,怎么定义一个block,怎样使用block.

block的声明与定义

首先,我们要明确block是什么,block是对象么?官方文档给了我们明确的答案,Block是对象.

// 声明:返回值(^block变量名)(参数)
    void(^block)();
// 定义
    // 方式一:无返回值无参数
    void(^block1)() = ^(){
        NSLog(@"调用block1");
    };
    // block如果没有参数,可以省略()
    void(^block1)() = ^{
        NSLog(@"调用block1");
    };
    // 方式二:有返回值无参数
    int(^block2)() = ^int{
        return 2;
    };
    // 方式三:无返回值有参数
    void(^block3)(int *value) = ^(int *value){
       
    };
   // 方式四:有返回值有参数
    int(^block3)(int *value) = ^int(int *value){
       return 2;
    };

block的开发使用场景

1.传值:我们知道在两个控制器之间逆传通常使用代理的方法,这种方法是标准的传值方式,这里我们用block的方式实现逆传.为了更好的区别代理和block的异同,代码里会进行对比,以便初学者更好的理解.

#import "ViewController.h"
#import "TestController.h"

@interface ViewController ()<TestControllerDelegate>

@property (nonatomic, strong) UITextField *textField;
@property (nonatomic, strong) UIButton *pushBtn;

@end

@implementation ViewController

-(UITextField *)textField
{
    if (!_textField) {
        
        _textField = [[UITextField alloc] initWithFrame:CGRectMake(70, 70, 100, 30)];
        _textField.backgroundColor = [UIColor redColor];
        _textField.placeholder = @"请输入";
    }
    return _textField;
}

-(UIButton *)pushBtn
{
    if (!_pushBtn) {
        _pushBtn = [UIButton buttonWithType:UIButtonTypeCustom];
        [_pushBtn setTitle:@"push" forState:UIControlStateNormal];
        [_pushBtn setTitleColor:[UIColor redColor] forState:UIControlStateNormal];
        _pushBtn.titleLabel.font = [UIFont systemFontOfSize:30];
        _pushBtn.frame = CGRectMake(70, 100, 100, 50);
        [_pushBtn addTarget:self action:@selector(clickedPushBtn) forControlEvents:UIControlEventTouchUpInside];
    }
    return _pushBtn;
}

-(void)clickedPushBtn
{
//    在push之前传值(顺传)
    TestController *testVC = [[TestController alloc] init];
    testVC.value = self.textField.text;
//    testVC.delegate = self;
//    block方式逆传
    testVC.valueBlock = ^(NSString *value){
        self.title = value;
    };
    [self.navigationController pushViewController:testVC animated:YES];
}

- (void)viewDidLoad {
    [super viewDidLoad];

    [self.view addSubview:self.textField];
    [self.view addSubview:self.pushBtn];
}

//#pragma mark - TestControllerDelegate
//-(void)clickBackBtn:(NSString *)string
//{
//    self.title = string;
//}

@end

注:这里可以看出,block其实就是一个特殊的数据类型,特殊在他是用来保存一段代码.

#import <UIKit/UIKit.h>
/*
@protocol TestControllerDelegate <NSObject>

@optional
-(void)clickBackBtn:(NSString *)string;

@end
*/

@interface TestController : UIViewController

@property(nonatomic, copy)NSString *value;

//@property(nonatomic, weak) id <TestControllerDelegate>delegate;

@property (nonatomic, strong) void(^valueBlock)(NSString *value);

@end

注:block怎么声明,就怎么来定义属性,这里需要强调的是如果你是在ARC环境下要用strong修饰.

#import "TestController.h"
#import "ViewController.h"

@interface TestController ()<UIGestureRecognizerDelegate>

@property (nonatomic, strong) UITextField *textField;
@property (nonatomic, strong) UIButton *backBtn;

@end

@implementation TestController

-(UITextField *)textField
{
    if (!_textField) {
        
        _textField = [[UITextField alloc] initWithFrame:CGRectMake(70, 70, 100, 30)];
        _textField.backgroundColor = [UIColor redColor];
        _textField.placeholder = @"请输入";
    }
    return _textField;
}

-(UIButton *)backBtn
{
    if (!_backBtn) {
        _backBtn = [UIButton buttonWithType:UIButtonTypeCustom];
        [_backBtn setTitle:@"返回" forState:UIControlStateNormal];
        [_backBtn setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
        [_backBtn sizeToFit];
        [_backBtn addTarget:self action:@selector(clickedBackBtn) forControlEvents:UIControlEventTouchUpInside];
    }
    return _backBtn;
}

-(void)clickedBackBtn
{
//    点击返回按钮的时候用代理方式实现逆传
//    if ([self.delegate respondsToSelector:@selector(clickBackBtn:)]) {
//        [self.delegate clickBackBtn:self.textField.text];
//    }
//    [self.navigationController popViewControllerAnimated:YES];
    
//    点击返回按钮的时候用block方式实现逆传
    if (self.valueBlock) {
        self.valueBlock(self.textField.text);
    }
    [self.navigationController popViewControllerAnimated:YES];
}

- (void)viewDidLoad {
    [super viewDidLoad];
    self.view.backgroundColor = [UIColor whiteColor];
    self.title = self.value;
    
    [self.view addSubview:self.textField];
    
    self.navigationItem.leftBarButtonItem = [[UIBarButtonItem alloc] initWithCustomView:self.backBtn];
//    清空手势代理,恢复滑动返回功能
    self.navigationController.interactivePopGestureRecognizer.delegate = self;

}

-(BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch
{
    return YES; 
}

@end

2.block作为参数使用

#import "ViewController.h"
#import "CalculateController.h"
@interface ViewController ()

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    CalculateController *calculateVC = [[CalculateController alloc] init];
    [calculateVC calculate:^int(int result) {
        result += 100;
        result *= 8;
        result += 88;
        return result;
    }];
    
//    打印结果
    NSLog(@"%d", calculateVC.result);
}

@end
#import <Foundation/Foundation.h>

@interface CalculateController : NSObject

@property(nonatomic, assign) int result;

-(void)calculate:(int(^)(int result))calculateBlock;

@end

注:这里要注意的是block作为参数使用的时候要怎么写,格式:返回值类型(^)(参数)block名称.

#import "CalculateController.h"

@implementation CalculateController

-(void)calculate:(int(^)(int result))calculateBlock
{
    self.result = calculateBlock(self.result);
}

@end

其实大量iOS系统方法使用block作为参数,比如我们最常用的[UIView animateWithDuration:<#(NSTimeInterval)#> animations:<#^(void)animations#> completion:<#^(BOOL finished)completion#>].

3.下面再给大家介绍一个比较装逼的用法,block作为返回值使用.

#import "ViewController.h"
#import "Calculate.h"
@interface ViewController ()

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    Calculate *calculate = [[Calculate alloc] init];
    calculate.add(8).add(8).add(8).add(8).add(8).add(8);
    NSLog(@"%d", calculate.result);//结果48
}

@end

注:这里是把方法调用通过.语法链接起来,只要是调用方法后面接(),就是把block当做返回值去用.

#import <Foundation/Foundation.h>

@interface Calculate : NSObject

@property(nonatomic, assign) int result;

-(Calculate *(^)(int value))add;

@end
#import "Calculate.h"

@implementation Calculate

-(Calculate *(^)(int value))add
{
    return ^Calculate *(int value){
        self.result += value;
        return self;
    };
}

@end
上一篇 下一篇

猜你喜欢

热点阅读