Block 代码块
前言
- iOS4.0开始,Block横空出世,自他出生开始,就深受Apple和开发者的喜爱.他其实就是c预言的补充,书面点说就是带有自动变量的匿名函数.
- 其实很多初级开发者也很喜欢使用Block,第一呢感觉他很简洁,代码的可读性也高,第二确实无形中提升了代码的逼格,
- Block 是一段预先准备好的代码,可以在需要的时候执行,可以当作参数传递。
- Block 可以作为函数参数或者函数的返回值,而其本身又可以带输入参数或返回值。
- Block 是C语言的,类似于一个匿名函数,它和传统的函数指针很类似,
- 但是Block是inline(内联函数)的,并且默认情况下它对局部变量是只读的。
- 苹果官方建议尽量多用 Block。在多线程、异步任务、集合遍历、集合排序、动画转场用的很多。
1、Block 的基本使用格式
- Block的格式
  
- 1.1 无参数无返回值- void(^tempBlock)() = ^() {
 NSLog(@"无参无返回值");
 }; // 调用
 tempBlock();
 
- 1.2 无参数有返回值- int(^tempBlock)() = ^() {
 return 10;
 }; // 调用的时候,无论你输入的是什么都返回的是10;
 tempBlock(100);
 
- 1.3 有参数无返回值- void(^tempBlock)(int) = ^(int temp) {
 NSLog(@"有参数无返回值");
 };
 
- 1.4 有参数有返回值- /* 定义了一个名叫 MySum 的 Block 对象,它带有两个 int 型参数,返回 int 型。等式右边就是 Block 的具体实现,大括号后需加分号 */
 int (^MySum)(int, int) = ^(int a, int b) {
 return a + b;
 }; // 调用 Block
 int sum = MySum(10, 12);
 
2、Block 的经典实用场景
- 2.1 修改外部变量- Block 可以访问局部变量,但是不能修改,如果要修改需加关键字 __block(双下划线)。
 - // 这样定义时,局部变量 sum 只能读取值不能修改,编译时会报错
 // int sum = 100;
 // 这样定义时,局部变量 sum 既可以读取值又能修改
 __block int sum = 100; void(^sumWithYBlock)(int) = ^(int y) {
 sum = sum + y;
 NSLog(@"new value %d", sum);
 }; 打印的值就是sum + y, 100 + 100 = 200
 sumXWithYBlock(100);
 
- 2.2 页面间的传值- 在第二个页面(SecondViewController)首先声明一个属性
 - /* 先声明block的名字,并确定参数的类型 */
 /* 要使用 copy 类型,格式:@property (nonatomic, copy) 返回值类型 (^变量名) (参数类型列表); */
 @property(nonatomic, copy) void (^netViewBlock)(NSString *text);
 - 在点击按钮返回的时候,往回传你需要传的参数,参数类型要一致
 - - (void)back {
 self.netViewBlock(@"你好");
 [self.navigationController popViewControllerAnimated:YES];
 }
 - 在第一页(FirstViewController),准备push进入下一页的时候,获取ViewController2的属性,并实现.
 - - (void)click:(UIButton *)sender {
 // 把第二页的返回的值显示在label上
 UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(30, 100, 200, 30)];
 [self.view addSubview:label];
 SecViewController *vc = [[SecViewController alloc] init]; vc.netViewBlock = ^(NSString *text) {
 label.text = text;
 };
 [self.navigationController pushViewController:vc animated:YES];
 }
 
- 2.3 自定义Block- 例子:点击Button,需要改变Button的title
- 实现:
- 创建一个工具类,声明一个类方法,并自定义一个block,需要传title,所以传参类型是NSString
 - @interface ChangeBuTitleTool : NSObject + (void)changeBuTitleWithText:(void(^)(NSString *titleText))text; @end
 - 实现
 - @implementation ChangeBuTitleTool
 + (void)changeBuTitleWithText:(void(^)(NSString *titleText))text {
 if (text) {
 text(@"键盘风筝");
 }
 }
 @end
 - 在控制器里Button的点击的时候,实现改变title的方法
 - - (void)addButton {
 UIButton *bu = [UIButton buttonWithType:(UIButtonTypeCustom)];
 bu.backgroundColor = [UIColor blueColor];
 bu.frame = CGRectMake(30, 90, 100, 50);
 [self.view addSubview:bu];
 [bu addTarget:self action:@selector(click:) forControlEvents:(UIControlEventTouchUpInside)];
 } - (void)click:(UIButton *)sender {
 [ChangeBuTitleTool changeBuTitleWithText:^(NSString *titleText) {
 [sender setTitle:titleText forState:(UIControlStateNormal)];
 }];
 }
 
- 2.4 Block与typedef的结合- 在上一个例子中, 声明一个类方法, 其中定义block直接写在类方法里, 看起来很不和谐,
- 尤其是对新手看起来可读性不太高, 可以用typedef单独定义一个block, 增加代码的可读性
 - // 这样看起来是不是整洁多了
 typedef void(^titleBlock)(NSString *titleText); @interface ChangeBuTitleTool : NSObject + (void)changeBuTitleWithText:(titleBlock)text;
 //+ (void)changeBuTitleWithText:(void(^)(NSString *titleText))text; @end @implementation ChangeBuTitleTool + (void)changeBuTitleWithText:(titleBlock)text {
 if (text) {
 text(@"键盘风筝");
 }
 }
 @end
 
3、Block 属性定义中为什么使用 copy 修饰
- ARC 开发的时候,编译器底层对 block 做过一些优化,使用 copy 修饰可以防止出现内存泄漏。
- 从内存管理的角度而言,程序员需要管理的内存只有堆区的。如果用 strong 修饰,相当于强引用了一个栈区的变量。
- 而使用 copy 修饰,在设置数值的时候,可以把局部变量从栈区复制到堆区。
// 用 copy 修饰定义属性
@property (nonatomic, copy) void (^myTask)();
// 定义,myBlock 是保存在栈区的,出了作用域,就应该被销毁
void (^myBlock)() = ^ {
    NSLog(@"hello");
};
// 用属性记录
self.myTask = myBlock;
// 执行
self.myTask();
4、循环引用
- 在 Block 中调用 self 容易产生循环引用,无法释放对象,在程序中可以使用析构方法判断是否产生了循环引用。
@implementation ViewController
// 在 Block 中调用 self 容易产生循环引用
[[QWebImageManager sharedManager] downloadImage:self.urlStr completion:^(UIImage *image) {
    self.image = image;
}];
@end
// 判断是否存在循环引用,无法释放时即存在循环引用
- (void)dealloc {
    NSLog(@"成功退出");
}
- 可以使用关键字 __weak 声明一个弱变量,或者为属性指定 weak 特性。如:
@implementation ViewController
// 弱引用 self,typeof(self) 等价于 ViewController
__weak typeof(self) weakSelf = self;
[[QWebImageManager sharedManager] downloadImage:self.urlStr completion:^(UIImage *image) {
    weakSelf.image = image;
}];
@end
Block 代码块的更多相关文章
- block(代码块)的介绍以及使用方法和变量之间的关系
		http://blog.csdn.net/menxu_work/article/details/8762848 block(代码块)的介绍以及使用方法和变量之间的关系 block(代码块)的介绍以及使 ... 
- block代码块介绍
		关于block的简单介绍 什么是block? Block是C语言的一个语法特性,同时也是C语言的运行时特性,它很像C中的函数指针,因为你可以像使用函数指针一样的去使用block对象:它也很像C++中的 ... 
- Block代码块中使用局部变量注意点
		第一次写代码遇到报这个错,实在是想不通为什么,按常理应该是不会有问题,报错的呀??纠结了一会之后只好仔细查看报错原因咯,原来是: 当我们在block代码块中使用局部变量时,就会很容易出现如图的错误. ... 
- IOS学习4——block代码块
		本文转载自:iOS开发-由浅至深学习block 一.关于block 在iOS 4.0之后,block横空出世,它本身封装了一段代码并将这段代码当做变量,通过block()的方式进行回调.这不免让我们想 ... 
- IOS Block代码块的定义与使用
		代码块的本质是和其他的变量类似,不同的是,代码块存储的数据是一个函数体.使用代码块,你可以像调用其他标准函数一样的调用,可以传入参数,并得到返回值. 脱字符是代码块的语法标记.下图表示代码块的 ... 
- OC Block(代码块)
		#import "ViewController.h" @interface ViewController () @end @implementation ViewControlle ... 
- iOS - OC Block  代码块
		前言 Block 是一段预先准备好的代码,可以在需要的时候执行,可以当作参数传递.Block 可以作为函数参数或者函数的返回值,而其本身又可以带输入参数或返回值.Block 是 C 语言的,类似于一个 ... 
- iOS - Block		代码块
		1.Block Block 是一段预先准备好的代码,可以在需要的时候执行,可以当作参数传递.Block 可以作为函数参数或者函数的返回值,而其本身又可以带输入参数或返回值.Block 是 C 语言的, ... 
- IOS学习之block代码块
		前言: block这个名词对于做一般开发者来说可能会觉得稀奇古怪而非常陌生,但是对于iOS工程师来说,在整个开发中到处都是它的影子,今天一大早觉得在假期学习一下它,对明年的iOS开发工作做个准备,突然 ... 
- iOS:使用block代码块实现事件处理过程中的回调
		block是什么,这里就不多加强调了,它的优点: 第一:执行效率高,速度快 第二:使用起来比代理简单,省却不少代码,增强代码美感 有一些小的知识点要强调一下: 第一点:它类似于一个匿名函数,也跟jav ... 
随机推荐
- Linux网络编程——I/O复用之poll函数
			一.回顾前面的select select优点: 目前几乎在所有的平台上支持,其良好跨平台支持也是它的一个优点 select缺点: 1.每次调用 select(),都需要把 fd 集合从用户态拷贝到内核 ... 
- Mybatis 一对一(OneToOne)关系映射__INSERT
			今天测试Ibatis的一对一的关联映射时总是出现错误,其中很多的错误都是自己不小心写错的..现把整个Ibatis源代码记录下来,以便以后熟记: 1.数据库脚本: CREATE TABLE t_pers ... 
- Celery-4.1 用户指南: Signals (信号)
			基础 有多种类型的事件可以触发信号,你可以连接到这些信号,使得在他们触发的时候执行操作. 连接到 after_task_publish 信号的示例: from celery.signals impor ... 
- 2015.4.21 SetWindowPos函数用法
			定义:[DllImport("user32.dll")] public static extern bool SetWindowPos(IntPtr hWnd, int hWndl ... 
- 问题:oracle long 与 clob;结果:long类型比clob到底差在什么地方?
			long类型比clob到底差在什经常看到9i以上的文档,说以后 clob会逐步取代long,一直想不出, 而我在8.1.7上也测试2个字段好像 在存储上也看不出什么区别?么地方? 差别还是很大的, 比 ... 
- Tomcat 不能正常启动
			启动过程提示: Stopping ProtocolHandler ["http-bio-8080"] the JRE_HOME environment variable is no ... 
- java定时器控制时间打印
			public class test2 { public static void main(String []args){ Timer timer=new Timer(); timer.schedule ... 
- Springboot中AOP统一处理请求日志
			完善上面的代码: 现在把输出信息由先前的system.out.println()方式改为由日志输出(日志输出的信息更全面) 现在在日志中输出http请求的内容 在日志中获取方法返回的内容 
- 中华人民共和国建筑工业行业标准—IFC详细解读 第五篇
- C#.NET中Dns类的常用方法及说明
			IP是一种普遍应用于因特网.允许不同主机能够相互找到对方的寻址协议.IP地址由4个十进制的数字号码所组成,而每一个号码的值介于0~255之间,它虽然解决了网络上计算机的识别问题,但是IP地址确不容易记 ... 
