/********************************************************************************************
* author:conowen@大钟
* E-mail:conowen@hotmail.com
* http://blog.csdn.net/conowen
********************************************************************************************/
1、Block的定义
2、Block的声明
//As a local variable:
returnType (^blockName)(parameterTypes) = ^returnType(parameters) {...};
//As a property:
@property (nonatomic, copy, nullability) returnType (^blockName)(parameterTypes);
//As a method parameter:
- (void)someMethodThatTakesABlock:(returnType (^nullability)(parameterTypes))blockName;
//As an argument to a method call:
[someObject someMethodThatTakesABlock:^returnType (parameters) {...}];
//As a typedef:
typedef returnType (^TypeName)(parameterTypes);
TypeName blockName = ^returnType(parameters) {...};
a、指针函数
//类型标识符 *函数名(参数表)
int *fun(x,y);
b、函数指针
<pre code_snippet_id="1695099" snippet_file_name="blog_20160527_11_8242247" name="code" class="objc">类型标识符 (*函数名)(参数表)
int (*fun) (int x,y); //函数名前面有一个星号,然后用小括号包起来
fun=funTest; /* 将funTest函数的首地址赋给指针
int (^fun) (int,int);
3、Block的应用场景
3.1、定义一个Block,然后输出打印信息
int (^addFun)(int,int) = ^int(int a,int b){
return a + b;
};
NSLog(@"addValue = %d",addFun(1,2));
打印消息是
2016-06-01 11:27:14.191 Runtime[10910:4558911] addValue = 3
3.2、Block与Delegate的区别
这是最简单的Block使用,一般我们使用Block来做一些有趣的事情,例如代替delegate,平常我们在不同的类传值的话,一般使用delegate,虽然也能实现,但是写法比较繁琐,用Block就能很轻松实现,而且代码量少了不少。
//
// ViewController.m
// Runtime
//
// Created by idealMac2 on 16/5/20.
// Copyright © 2016年 GValley. All rights reserved.
//
#import "ViewController.h"
#import "SecondViewController.h"
@interface ViewController () <SecondViewControllerDelegate>
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
UIButton *btn = [[UIButton alloc] initWithFrame:CGRectMake(100, 200, 60.0, 20.0)];
[btn setTitle:@"open" forState:UIControlStateNormal];
[btn setTitleColor:[UIColor darkGrayColor] forState:UIControlStateNormal];
[btn addTarget:self action:@selector(openAction:) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:btn];
}
- (void)openAction:(id)sender{
NSLog(@"openAction");
SecondViewController *secondViewController = [SecondViewController new];
secondViewController.callBackValue = ^ void (NSString *str){
NSLog(@"Block str = %@",str);
};
secondViewController.delegate = self;
[self presentViewController:secondViewController animated:YES completion:nil];
}
#pragma mark SecondViewControllerDelegate
- (void)closeAction:(NSString *) str{
NSLog(@"delegate str = %@",str);
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
@end
第二个ViewController的头文件如下
//
// SecondViewController.h
// Runtime
//
// Created by idealMac2 on 16/6/1.
// Copyright © 2016年 GValley. All rights reserved.
//
#import <UIKit/UIKit.h>
//声明delegate
@protocol SecondViewControllerDelegate <NSObject>
@optional
- (void)closeAction:(NSString *) str;
@end
@interface SecondViewController : UIViewController
//声明Block
@property (nonatomic,copy) void(^callBackValue)(NSString *);
@property (nonatomic,weak) id<SecondViewControllerDelegate> delegate;
@end
//
// SecondViewController.m
// Runtime
//
// Created by idealMac2 on 16/6/1.
// Copyright © 2016年 GValley. All rights reserved.
//
#import "SecondViewController.h"
@interface SecondViewController ()
@end
@implementation SecondViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
UIButton *btn = [[UIButton alloc] initWithFrame:CGRectMake(100, 200, 60.0, 20.0)];
[btn setTitle:@"close" forState:UIControlStateNormal];
[btn setTitleColor:[UIColor darkGrayColor] forState:UIControlStateNormal];
[btn addTarget:self action:@selector(closeAction:) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:btn];
}
- (void)closeAction:(id)sender{
NSString *strA = @"closed";
//Block的方式
self.callBackValue(strA);
//Delegate的方式
if (self.delegate && [self.delegate respondsToSelector:@selector(closeAction:)]) {
[self.delegate closeAction:strA];
}
[self dismissViewControllerAnimated:YES completion:nil];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
/*
#pragma mark - Navigation
// In a storyboard-based application, you will often want to do a little preparation before navigation
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
// Get the new view controller using [segue destinationViewController].
// Pass the selected object to the new view controller.
}
*/
@end
2016-06-01 12:10:31.211 Runtime[10959:4573582] block str = closed
2016-06-01 12:10:31.211 Runtime[10959:4573582] delegate str = closed
4、Block与外部变量的关系
int c = 0;
int (^addFun)(int,int) = ^int(int a,int b){
return a + b + c;
};
NSLog(@"addValue = %d",addFun(1,2));
但是如果要修改外部变量,就会出现无法修改的问题,同时,使用外部变量,也会存在引起循环引用的问题。
4.1、如何修改Block外部变量
static int c = 0;//静态变量
int (^addFun)(int,int) = ^int(int a,int b){
c = 1;
return a + b + c;
};
NSLog(@"addValue = %d",addFun(1,2))
还有一种方法就是通过在变量外部加上“__block”说明符,其实加了__Block之后,这个变量就变成了一个结构体指针变量,这个原理和静态变量一样,由传值方式改为指针传递,所以就可以更改变量了。
__block int c = 0;
int (^addFun)(int,int) = ^int(int a,int b){
c = 1;
return a + b + c;
};
NSLog(@"addValue = %d",addFun(1,2));