iOS4.0系统已经开始支持Block,在编程过程中,block被OC看成是对象,它封装了一段代码,这段代码可以在任何时候执行。Block可以作为函数参数或者函数的返回值,而其本身又可以带输入参数或者返回值。Blcok的定义式如下:
返回值类型(也可以不返回,这是写void) (^名称)(传入的参数(一个或多个或不传))= (^传入的参数){
//具体实现方法
}
Block和传统的函数指针很类似,但是还是有所区别的:block是inline的,并且它对局部变量是只读的,可以在block块里使用局部变量,但是不能改变局部变量的值,因为在block块里使用的时候是Copy过来的,不在是原来的变量了,所以不可以对其改变值。如果要是想改变值的话可以用__block或者static定义变量,代码如下:
__block int number = 100;
void (^blockNumner)() = ^(){
number ++;
}
Block做为property属性可以实现页面之间的传值。block传值相对代理来说要简单一些,不用声明协议,实现协议方法等等,只要创建block,传值即可使用,实现第二个界面的数据传到第一个界面上的功能,代码如下:
第一个界面
//.h
#import <UIKit/UIKit.h>
//创建block
typedef void(^blockStr)(NSString *str);
@interface FirstViewController : UIViewController
@property (nonatomic, copy)blockStr BStr;
@end
//.m
#import "FirstViewController.h"
@interface FirstViewController ()
@property (nonatomic, strong) UITextField *tf;
@end
@implementation FirstViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
self.view.backgroundColor = [UIColor whiteColor];
_tf = [[UITextField alloc]initWithFrame:CGRectMake(20, 100, self.view.frame.size.width-40, 30)];
//_tf.borderStyle = UIText
_tf.layer.borderWidth = 1.0;
_tf.layer.borderColor = [UIColor groupTableViewBackgroundColor].CGColor;
[self.view addSubview:_tf];
//添加手势,取消视图
UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc]initWithTarget:self action:@selector(cancel)];
[self.view addGestureRecognizer:tap];
}
- (void)cancel
{
//当第二个界面开始消失的时候,传值
[_tf resignFirstResponder];
if (self.BStr) {
self.BStr(self.tf.text);
}
[self dismissViewControllerAnimated:YES completion:nil];
}
第二个界面
#import "ViewController.h"
#import "FirstViewController.h"
@interface ViewController ()
@property (nonatomic, strong) UILabel *label;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
_label = [[UILabel alloc]initWithFrame:CGRectMake(20, 100, self.view.frame.size.width-40, 60)];
_label.layer.borderColor = [UIColor groupTableViewBackgroundColor].CGColor;
_label.layer.borderWidth = 1.0;
[_label.layer setMasksToBounds:YES];
[_label.layer setCornerRadius:5.0];
[self.view addSubview:_label];
UIButton *button = [[UIButton alloc]initWithFrame:CGRectMake(60, CGRectGetMaxY(_label.frame)+20, self.view.frame.size.width-120, 60)];
[button setTitle:@"点我" forState:0];
button.backgroundColor = [UIColor yellowColor];
[button setTitleColor:[UIColor blackColor] forState:0];
[button.layer setMasksToBounds:YES];
[button.layer setCornerRadius:5.0];
[button addTarget:self action:@selector(btnClick) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:button];
}
- (void)btnClick
{
//在点击按钮,跳转到第二个界面的按钮响应事件里实现赋值block的传值。
FirstViewController *first = [[FirstViewController alloc]init];
first.BStr = ^(NSString *bstr){
self.label.text = bstr;
};
[self presentViewController:first animated:YES completion:nil];
}
感觉平时block用的也不是很多啊,大多都是在大牛们封装好的第三方里见过,如刷新的控件啊(MJRefresh),而且block使用最多的就是传值方面了吧。下面是我对AFNetworking的重新封装,可以一个方法做各种请求,不用再每次请求数据的时候都创建请求控制器,用的就是block的传值,代码如下:
AFNetworking3.0更新了方法,AFURLConnectionOperation,AFHTTPRequestOperation,AFHTTPRequestOperationManager这几个类已经被废弃
首先创建一个NSObject的类,在.h文件里写一个请求数据的方法
#import <Foundation/Foundation.h>
@interface Request : NSObject
//get请求
+ (void)requestData:(NSString *)string widthBlcok:(void (^)(NSDictionary *dic))block ;
//post请求,拼接data
+ (void)requestData:(NSString *)string withDicAndData:(NSDictionary *)dict widthBlcok:(void (^)(NSDictionary *dic))block ;
//post请求,不拼接data
+ + (void)requestData:(NSString *)string withDic:(NSDictionary *)dict widthBlcok:(void (^)(NSDictionary *dic))block ;
@end
在.m文件里实现具体的请求方法,并传值。
#import "Request.h"
#import <AFNetworking.h>
@implementation Request
+ (void)requestData:(NSString *)string widthBlcok:(void (^)(NSDictionary *dic))block
{
AFHTTPSessionManager *request = [AFHTTPSessionManager manager];
request.responseSerializer = [AFHTTPResponseSerializer serializer];
//get请求
[request GET:string parameters:nil progress:^(NSProgress * _Nonnull downloadProgress) {
NSLog(@"progress!");
} success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {
// NSLog(@"%@",responseObject);
NSDictionary *dic = [NSJSONSerialization JSONObjectWithData:responseObject options:NSJSONReadingMutableContainers | NSJSONReadingMutableLeaves error:nil];
if (block) {
block(dic);
}
} failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
NSLog(@"error:%@",error);
}];
}
+(void)requestData:(NSString *)string withDicAndData:(NSDictionary *)dict widthBlcok:(void (^)(NSDictionary *))block
{
//post请求,拼接data二进制流
AFHTTPSessionManager *request = [AFHTTPSessionManager manager];
request.responseSerializer = [AFHTTPResponseSerializer serializer];
//post请求
[request POST:string parameters:nil constructingBodyWithBlock:^(id<AFMultipartFormData> _Nonnull formData) {
//上传图片 ,以文件流的格式
[formData appendPartWithFileData:dict[@"data"] name:@"avatar" fileName:dict[@"fileName"] mimeType:@"image/png"];
} progress:^(NSProgress * _Nonnull uploadProgress) {
NSLog(@"progress!");
} success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {
NSDictionary *dic = [NSJSONSerialization JSONObjectWithData:responseObject options:NSJSONReadingMutableContainers | NSJSONReadingMutableLeaves error:nil];
if (block) {
block(dic);
}
} failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
NSLog(@"error:%@",error);
}];
}
+ + (void)requestData:(NSString *)string withDic:(NSDictionary *)dict widthBlcok:(void (^)(NSDictionary *dic))block
{
AFHTTPSessionManager *request = [AFHTTPSessionManager manager];
request.responseSerializer = [AFHTTPResponseSerializer serializer];
//post请求,不拼接data二进制流
[request POST:string parameters:nil progress:^(NSProgress * _Nonnull uploadProgress) {
NSLog(@"progress!");
} success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {
NSDictionary *dic = [NSJSONSerialization JSONObjectWithData:responseObject options:NSJSONReadingMutableContainers | NSJSONReadingMutableLeaves error:nil];
if (block) {
block(dic);
}
} failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
NSLog(@"error:%@",error);
}];
}
在需要用这些值的页面里包含创建的类的头文件,然后取出所传的值
//传不同的URL,获取不同的数据。
//get请求
[Request requestData:@"your---url" widthBlcok:^(NSDictionary *dic) {
NSLog(@"---%@",dic);
}];
NSDictionary *dict = @{@"":@"",@"":@""};
//post请求,拼接data
[Request requestData:@"your---url" withDicAndData:dict widthBlcok:^(NSDictionary *dic) {
NSLog(@"-----%@",dic);
}];
//post请求,不拼接data
[Request requestData:@"your---url" withDic:dict widthBlcok:^(NSDictionary *dic) {
NSLog(@"-----%@",dic);
}];