如何在iOS中使用ios block详解

1657人阅读
1 什么是block
iOS SDK 4.0开始,Apple引入了block这一特性。字面上说,block就是一个代码块,但是它的神奇之处在于在内联(inline)执行的时候(这和C++很像)还可以传递参数。同时block本身也可以被作为参数在方法和函数间传递,这就给予了block无限的可能。 & &&
& & & &对于闭包(block),有很多定义,其中闭包就是能够读取其它函数内部变量的函数,这个定义即接近本质又较好理解。对于刚接触Block的同学,会觉得有些绕,因为我们习惯写这样的程序main(){ funA();} funA(){funB();} funB(){.....}; 就是函数main调用函数A,函数A调用函数B... 函数们依次顺序执行,但现实中不全是这样的,例如项目经理M,手下有3个程序员A、B、C,当他给程序员A安排实现功能F1时,他并不等着A完成之后,再去安排B去实现F2,而是安排给A功能F1,B功能F2,C功能F3,然后可能去写技术文档,而当A遇到问题时,他会来找项目经理M,当B做完时,会通知M,这就是一个异步执行的例子。在这种情形下,Block便可大显身手,因为在项目经理M,给A安排工作时,同时会告诉A若果遇到困难,如何能找到他报告问题(例如打他手机号),这就是项目经理M给A的一个回调接口,要回掉的操作,比如接到电话,百度查询后,返回网页内容给A,这就是一个Block,在M交待工作时,已经定义好,并且取得了F1的任务号(局部变量),却是在当A遇到问题时,才调用执行,跨函数在项目经理M查询百度,获得结果后回调该block。
block是一个特殊的OC对象, 它建立在栈上, 而不是堆上, 这么做一个是为性能考虑,还有就是方便访问局部变量.
默认情况下block使用到的局部变量都会被复制,而不是保留.
所以它无法改变局部变量的值.
如果在变量面前加上__block, 那么编译器回去不会复制变量, 而是去找变量的地址, 通过地址来访问变量, 实际上就是直接操作变量.
另外块是在栈上分配的, 所以一旦离开作用域, 就会释放, 因此如果你要把快用在别的地方, 必须要复制一份.
所以在属性定义一个快的时候需要使用copy: &@property (nonatomic, copy) void (^onTextEntered)(NSString *enteredText);
块是不能保留的, retain对块没有意义.
2 block 实现原理
Objective-C是对C语言的扩展,block的实现是基于指针和函数指针。
从计算语言的发展,最早的goto,高级语言的指针,到面向对象语言的block,从机器的思维,一步步接近人的思维,以方便开发人员更为高效、直接的描述出现实的逻辑(需求)。
iOS中block实现的探究
谈Objective-C Block的实现
3 block的使用
A:cocoaTouch框架下动画效果的Block的调用
动画效果是IOS界面重要的特色之一,其中CAAnimation是所有动画对象的抽象父类,作为新人,使用较多的是UIView下的动画方法(类方法)。使用UIView下的动画,有下面几个方法。
方法一:设置beginAnimations
其中memberView为需要添加的子视图的视图,mivc.view为子视图,在使用的时候,需要将这两个地方替换
需要注意的是,一定要使用[UIView commitAnimations];动画才会生效
通过[UIView setAnimationDuration:1]; 设置持续时间。
在IOS4.0后,我们有了新的方法,+ (void)transitionWithView:(UIView *)view duration:(NSTimeInterval)duration options:(UIViewAnimationOptions)options animations:(void (^)(void))animations completion:(void (^)(BOOL finished))completion,依然是UIView的类方法,但使用到了Block对象,Block对象是一组指令,可以传递(像变量一样),可以把它想像成C语言的函数指针。
[UIView transitionWithView:self.view
& & & & & & & & & & & & & duration:0.2
& & & & & & & & & & & & & &options:UIViewAnimationOptionTransitionFlipFromLeft
& & & & & & & & & & & & animations:^{ [self.view addSubview:yellowView.view]; }
& & & & & & & & & & & & completion:NULL];
使用typed声明block
typedef void(^didFinishBlock) (NSObject *ob);
这就声明了一个didFinishBlock类型的block,
然后便可用
@property (nonatomic,copy) didFinishBlock &finishB
声明一个block对象,注意对象属性设置为copy,接到block 参数时,便会自动复制一份。&
__block是一种特殊类型,
使用该关键字声明的局部变量,可以被block所改变,并且其在原函数中的值会被改变。
C:1 使用block和使用delegate完成委托模式有什么优点?
block不同其它变量的原因在于它不是一个单一变量, 而是一个方法,
我们要传递的是一个代码块,并且这个代码块可以存在参数,
这个参数并不是在定义block的时候就赋予值, 而是我们在实际运行block的时候才赋予值.&
因此对于有参数的block,当我们传递过去的时候, 它的需要接收方提供相应的参数才能运行,&
这么做我们就可以在A类为B类将来会发生的事件提前做好处理的方法,即使我们还没有这些事件的具体参数.
某种意义上将这样就不需要两者之间的委托关系.
委托关系就是B类发生一个事件后,通知A类,让A类再针对这个事件进行一些处理
&而使用block,则是A已经提前将这个事件的处理方法告诉了B类, 等时间发生的时候, B类无需通知A类, 直接运行实现设置好的处理方法(block)即可.
&如果你在运行一个方法的时候又想告诉这个方法在某一特定情况你还要怎么做的话, 就可以使用Block.
GCD主要使用block来代替委托模式,使程序变得简洁,同时运行效率也得到提高.
& & static int clickNum = 0;
& & self.Mylabel = [[UILabel alloc]init];
& & while (clickNum &20) {
& & & & dispatch_async(dispatch_get_main_queue(), ^{
& & & & & & self.Mylabel.text = [NSString stringWithFormat:@&%d&,clickNum++];//UI的绘制必须在主线程中
& & & & });
& & & & [NSThread sleepForTimeInterval:1];
关于block和GCD可以参考这篇文章:
还有这篇文章
ARC和非ARC中block的区别:
ARC下Block何时会从栈自动被复制到推, 以及__block和__weak的使用问题
由于Block是默认建立在栈上, 所以如果离开方法作用域, Block就会被丢弃, 在非ARC情况下, 我们要返回一个Block ,需要 [Block copy];
在ARC下, 以下几种情况, Block会自动被从栈复制到堆:
1.被执行copy方法
2.作为方法返回值
3.将Block赋值给附有__strong修饰符的id类型的类或者Blcok类型成员变量时
4.在方法名中含有usingBlock的Cocoa框架方法或者GDC的API中传递的时候.
对于非ARC下, 为了防止循环引用, 我们使用__block来修饰在Block中实用的对象:
__block id blockSelf=
self.blk=^{
NSLog(@&%@&,blockSelf); &//在非ARC下对于栈上的_block对象, Block不会对其复制, 仅仅使用, 不会增加引用计数.
对于ARC下, 为了防止循环引用, 我们使用__weak来修饰在Block中实用的对象:
__weak id weakSelf=
self.blk=^{
NSLog(@&%@&,weakSelf);
如果要在ARC下, 为了防止循环引用, 使用__block来修饰在Block中实用的对象,仍然会被retain, 所以需要多做一些设置
__block id blockSelf=
self.blk=^{
NSLog(@&%@&,blockSelf);
self.blk= & //blk被释放, blk只有的blockSelf也就被释放了
blk(); & //并且一定要运行一次, 否则不能被释放
这样就使blk断开了与blockSelf的持有关系.
这么多好处是可以自己控制对self的持有时间.
不过在最新的ios版本中, 这些会始终被已叹号形式提示存在循环引用问题.&
这种书写方式不被推荐. 除非你要在block中修改__block的指针指向.
其实我们用使用__weak修饰符, 只是不能修改对象本身, 但是可以修改对象的属性.&
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:349869次
积分:5446
积分:5446
排名:第1657名
原创:175篇
转载:67篇
评论:193条
(4)(2)(3)(8)(12)(7)(23)(3)(8)(7)(21)(6)(10)(40)(19)(3)(12)(17)(1)(1)(13)(4)(10)(2)(6)(1)(1)19955人阅读
Block简介:
Block的实际行为和Function很像,最大的差别是在可以存取同一个Scope的变量值。Block实体形式如下:
^(传入参数列){行为主体};
Block实体开头是“^”,接着是由小括号所包起来的参数列(比如 int a, int b, int c),行为主体由大括号包起来,专有名字叫做block literal。行为主体可以用return回传值,类型会被compiler自动辨别。如果没有参数列要写成:
例如下面的一个例子:
^(int a){return a*a;};
这是代表Block会回传输入值的平方值(int a 就是参数列, return a*a; 就是行为主体)。记得行为主体里最后要加“;”,因为是叙述,而整个{}最后也要加“;”,因为Block是物件实体。用法如下:
int result = ^(int a){return a*a;}(5);
NSLog(@&%d&, result);
很奇怪吧?后面的小括号里面的5会被当成a的输入值,然后经由Block输出 5*5 = 25指定给result这个变量。
有没有简单一点的方法嗯?不然每次都写这么长?有。接下来介绍一个叫做Block Pointer的东西来简化我们的写法。
Block Pointer是这样定义的:
回传值(^名字)(参数列);
比如下面的例子:
//声明一个square的Block Pointer,其所指向的Block有一个int输入和int输出
int (^square)(int);
//将Block实体指定给square
square = ^(int a){ return a* };
//调用方法,感觉是是不是很像function的用法?
int result = square(5);
NSLog(@&%d&, result);是不是变的简单了?
也可以吧Block Pointer当成参数传递给一个function,比如:
void myFunction(int (^mySquare)(int));
//function的定义,将Block作为参数
int (^mySquare)(int) = ^(int a){return a*a;};
//定义一个mySquare的Block pointer变量
myFunction(mySquare);
//把mySquare作为myFunction的参数
上面的三行代码其实等价于下面这行代码:
myFunction( ^int(int a){return a*a;} );
当其作为Object-C method的传入值的话,需要把类型写在变量前面,然后加上小括号。比如下面这种写法:
-(void)objcMethod:(int(^)(int))
//square参数的类型是int(^)(int)
1、可以读取和Block pointer同一个Scope的变量值:
int outA = 8;
int (^myPtr)(int) = ^(int a){ return outA +};
//block里面可以读取同一类型的outA的值
int result = myPtr(3);
// result is 11
NSLog(@&result=%d&, result);
下面来看一段很有意思的代码:
int outA = 8;
int (^myPtr)(int) = ^(int a){ return outA +}; //block里面可以读取同一类型的outA的值
//在调用myPtr之前改变outA的值
int result = myPtr(3);
// result的值仍然是11,并不是8
NSLog(@&result=%d&, result);
为什么result 的值仍然是11?而不是8呢?事实上,myPtr在其主体中用到的outA这个变量值的时候做了一个copy的动作,把outA的值copy下来。所以,之后outA即使换成了新的值,对于myPtr里面copy的值是没有影响的。
需要注意的是,这里copy的值是变量的值,如果它是一个记忆体的位置(地址),换句话说,就是这个变量是个指针的话,
它的值是可以在block里被改变的。如下例子:
NSMutableArray *mutableArray = [NSMutableArray arrayWithObjects:@&one&, @&two&, @&three&, nil];
int result = ^(int a){[mutableArray removeLastObject]; return a*a;}(5);
NSLog(@&test array :%@&, mutableArray);
原本mutableArray的值是{@&one&,@&two&,@&three&},在block里面被更改mutableArray后,就变成{@&one&,&@&two&}了。
2、直接存取static类型的变量
static int outA = 8;
int (^myPtr)(int) = ^(int a){return outA +};
int result = myPtr(3);
//result的值是8,因为outA是static类型的变量
NSLog(@&result=%d&, result);
甚至可以直接在block里面修改outA的值,例如下面的写法:
static int outA = 8;
int (^myPtr)(int) = ^(int a){ outA = 5; return outA +};
int result = myPtr(3);
//result的值是8,因为outA是static类型的变量
NSLog(@&result=%d&, result);
3、Block Variable类型的变量
在某个变量前面如果加上修饰字“__block”的话(注意,block前面有两个下划线),这个变量就称作block variable。
那么在block里面就可以任意修改此变量的值,如下代码:
__block int num = 5;
int (^myPtr)(int) = ^(int a){return num++;};
int (^myPtr2)(int) = ^(int a){return num++;};
int result = myPtr(0);
//result的值为5,num的值为6
result = myPtr2(0);
//result的值为6,num的值为7
NSLog(@&result=%d&, result);
因为myPtr和myPtr2都有用到num这个block variable,最终num的值为7.
未完待续。。
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:506880次
积分:4431
积分:4431
排名:第2380名
原创:59篇
转载:22篇
评论:180条
(1)(2)(1)(1)(2)(4)(2)(4)(2)(4)(2)(1)(3)(13)(5)(2)(17)(15)-------------
新增文件夹...
新增文件夹
(多个标签用逗号分隔)
iOS下用block+GCD来在程序中实现非阻塞式.docx
本文用示例来说明一下iOS下用block+GCD来在程序中实现非阻塞式执行耗时任务。先说明一下,严格说来“异步”、“后台线程”、“非阻塞”这些概 念是有一些小区别的。有些系统API特别是网络和文件I/O是通过系统底层中断来实现”非阻塞”,而一般用户任务比如耗时计算是通过后台线程完成的。但具 体到app这一层,开发人员并不关心具体的实现是用了硬件中断还是一个线程,所以在本文的上下文中,没有特意区分这
本文用示例来说明一下iOS下用block+GCD来在程序中实现非阻塞式执行耗时任务。先说明一下,严格说来“异步”、“后台线程”、“非阻塞”这些概 念是有一些小区别的。有些系统API特别是网络和文件I/O是通过系统底层中断来实现”非阻塞”,而一般用户任务比如耗时计算是通过后台线程完成的。但具 体到app这一层,开发人员并不关心具体的实现是用了硬件中断还是一个线程,所以在本文的上下文中,没有特意区分这几个概念点,甚至有些混用。本文中的 “非阻塞”可以简章理解为,开发人员只需要知道“我的程序执行耗时任务时,UI仍然可以响应用户操作”。&&
加载中...!如果长时间没有加载,请刷新页面
下载本文档需要登录,并付出相应积分()。购买积分->。
文件大小:109.12 KB
所需积分:& 2
iOS下用block+GCD来在程序中实现非阻塞式.docx
文件大小:109.12 KB &&&&所需积分:& 2
本次下载将耗费您2个积分(说明:不需要积分就可以下载)重复下载将不扣积分!如果想购买积分,
相关资讯  — 
相关讨论话题  — 
浏览:1392次&& 下载:1次
格式:docx
上传时间: 19:28:20
同类热门文档
14891次浏览 &46次下载
16806次浏览 &10次下载
28189次浏览 &10次下载
9859次浏览 &14次下载
7632次浏览 &13次下载
5246次浏览 &1次下载
相关经验 -
& 3人评&62页
& 5人评&88页
& 52人评&93页
& 0人评&1页
& 0人评&4页
OPEN-OPEN, all rights reserved.iOS4 标签_51CTO技术博客
搜索推荐文章
搜索原创文章
搜索近期文章
&&&&Block可以帮助我们组织独立的代码段,并提高复用性和可读性。iOS4在UIKit中引入了该特征。超过100个的AppleAPI都使用了Block,所以这是一个我们必须开始熟悉的知识。
Block是什么样的?
你可以使用^操作符来声明一个Block变量,它表示一个Block的开始。
intnum1=7;int(^aBloc..
&&&&iPhone4采用了一个叫做retina的屏幕,尺寸和老的iphone一样大,但是分辨率提高了4倍,看起高清的图来,爽太多了,根本看不到像素点.对于老的app来说,在iphone4中运行,会自动用4个像素替代原来的一个像素,这样就不用更改代码,使得老app可以自然的在iphone4中运行,但是UI的效果会有些蒙..
Copyright&
版权所有 未经许可 请勿转载

我要回帖

更多关于 ios block循环引用 的文章

 

随机推荐