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