iOS之 开发学习笔记-block
2015-11-12 15:05
211 查看
block在oc中是一个比较好用的“代码块”可以用来传递参数,回调等等相对于大工程block要比代理
好的多相信大家也都被工程里繁多的代理弄得晕来晕去。
block ——》 (void) (^blockname )()
其中,定义了一个名字为aBlock的blocks对象,并携带了相关信息:
1、aBlock 有两个形式参数,分别为int类型;
2、aBlock 的返回值为int 类型;
3、等式右边就是blocks的具体实现;
4、^ 带边blocks声明和实现的标示(关键字);
当然,你可以定义其他形式的block。e.g:无返回值,无形式参数等;
2、blocks 访问权限
blocks可以访问局部变量,但是不能修改。
?
此处不能修改的原因是在编译期间确定的,编译器编译的时候把a的值复制到block作为一个新变量(假设是a‘ = 10),此时a'和a是没有关系的。
这个地方就是函数中的值传递。如果要修改就要加关键字:__block或者static
3、block的调用
block调用就像调用函数一样。e.g:
4、block 应用
假设我们熟悉代理递值的话,对代理我们可能又爱有恨!我们先建立模型A页面 push B页面,如果把A页面的值传递到B页面,属性和单例传值可以搞定!但是如果Pop过程中把B页面的值传递到A页面,那就可以用单例或者代理了!说到代理,我们要先声明协议,创建代理,很是麻烦。常常我们传递一个数值需要在两个页面间写很多代码,这些代码改变页面的整体顺序,可读性也打了折扣。所以,此时,block是一种优化方案!
5、 block的内存管理
block本身是像对象一样可以retain,和release。但是,block在创建的时候,它的内存是分配在栈(stack)上,而不是在堆(heap)上。他本身的作于域是属于创建时候的作用域,一旦在创建时候的作用域外面调用block将导致程序崩溃。比如下面的例子。 我在view did load中创建了一个block:
- (void)viewDidLoad
{
[superviewDidLoad];
int number = 1;
_block = ^(){
NSLog(@number %d, number);
};
}
并且在一个按钮的事件中调用了这个block:
- (IBAction)testDidClick:(id)sender {
_block();
}
此时我按了按钮之后就会导致程序崩溃,解决这个问题的方法就是在创建完block的时候需要调用copy的方法。copy会把block从栈上移动到堆上,那么就可以在其他地方使用这个block了~ 修改代码如下:
?
_block = ^(){
NSLog(@number %d, number);
};
_block = [_block copy];
同理,特别需要注意的地方就是在把block放到集合类当中去的时候,如果直接把生成的block放入到集合类中,是无法在其他地方使用block,必须要对block进行copy。不过代码看上去相对奇怪一些:
[array addObject:[[^{
NSLog(@hello!);
} copy] autorelease]];
6、循环引用
对于非ARC下, 为了防止循环引用, 我们使用__block来修饰在Block中使用的对象:
对于ARC下, 为了防止循环引用, 我们使用__weak来修饰在Block中使用的对象。原理就是:ARC中,Block中如果引用了__strong修饰符的自动变量,则相当于Block对该变量的引用计数+1。
这一点其实是在第一点的一个小的衍生。当在block内部使用成员变量的时候,比如
@interface ViewController : UIViewController
{
NSString *_string;
}
@end
在block创建中:
_block = ^(){
NSLog(@string %@, _string);
};
这里的_string相当于是self->_string;那么block是会对内部的对象进行一次retain。也就是说,self会被retain一次。当self释放的时候,需要block释放后才会对self进行释放,但是block的释放又需要等self的dealloc中才会释放。如此一来变形成了循环引用,导致内存泄露。
修改方案是新建一个__block scope的局部变量,并把self赋值给它,而在block内部则使用这个局部变量来进行取值。因为__block标记的变量是不会被自动retain的。
?
__block ViewController *controller = self;
_block = ^(){
NSLog(@string %@, controller->_string);
};
好的多相信大家也都被工程里繁多的代理弄得晕来晕去。
block ——》 (void) (^blockname )()
其中,定义了一个名字为aBlock的blocks对象,并携带了相关信息:
1、aBlock 有两个形式参数,分别为int类型;
2、aBlock 的返回值为int 类型;
3、等式右边就是blocks的具体实现;
4、^ 带边blocks声明和实现的标示(关键字);
当然,你可以定义其他形式的block。e.g:无返回值,无形式参数等;
blocks可以访问局部变量,但是不能修改。
?
这个地方就是函数中的值传递。如果要修改就要加关键字:__block或者static
block调用就像调用函数一样。e.g:
1 | int c = aBlock(10,10); bBlock(); |
假设我们熟悉代理递值的话,对代理我们可能又爱有恨!我们先建立模型A页面 push B页面,如果把A页面的值传递到B页面,属性和单例传值可以搞定!但是如果Pop过程中把B页面的值传递到A页面,那就可以用单例或者代理了!说到代理,我们要先声明协议,创建代理,很是麻烦。常常我们传递一个数值需要在两个页面间写很多代码,这些代码改变页面的整体顺序,可读性也打了折扣。所以,此时,block是一种优化方案!
5、 block的内存管理
block本身是像对象一样可以retain,和release。但是,block在创建的时候,它的内存是分配在栈(stack)上,而不是在堆(heap)上。他本身的作于域是属于创建时候的作用域,一旦在创建时候的作用域外面调用block将导致程序崩溃。比如下面的例子。 我在view did load中创建了一个block:
- (void)viewDidLoad
{
[superviewDidLoad];
int number = 1;
_block = ^(){
NSLog(@number %d, number);
};
}
并且在一个按钮的事件中调用了这个block:
- (IBAction)testDidClick:(id)sender {
_block();
}
此时我按了按钮之后就会导致程序崩溃,解决这个问题的方法就是在创建完block的时候需要调用copy的方法。copy会把block从栈上移动到堆上,那么就可以在其他地方使用这个block了~ 修改代码如下:
?
NSLog(@number %d, number);
};
_block = [_block copy];
同理,特别需要注意的地方就是在把block放到集合类当中去的时候,如果直接把生成的block放入到集合类中,是无法在其他地方使用block,必须要对block进行copy。不过代码看上去相对奇怪一些:
[array addObject:[[^{
NSLog(@hello!);
} copy] autorelease]];
6、循环引用
对于非ARC下, 为了防止循环引用, 我们使用__block来修饰在Block中使用的对象:
对于ARC下, 为了防止循环引用, 我们使用__weak来修饰在Block中使用的对象。原理就是:ARC中,Block中如果引用了__strong修饰符的自动变量,则相当于Block对该变量的引用计数+1。
这一点其实是在第一点的一个小的衍生。当在block内部使用成员变量的时候,比如
@interface ViewController : UIViewController
{
NSString *_string;
}
@end
在block创建中:
_block = ^(){
NSLog(@string %@, _string);
};
这里的_string相当于是self->_string;那么block是会对内部的对象进行一次retain。也就是说,self会被retain一次。当self释放的时候,需要block释放后才会对self进行释放,但是block的释放又需要等self的dealloc中才会释放。如此一来变形成了循环引用,导致内存泄露。
修改方案是新建一个__block scope的局部变量,并把self赋值给它,而在block内部则使用这个局部变量来进行取值。因为__block标记的变量是不会被自动retain的。
?
_block = ^(){
NSLog(@string %@, controller->_string);
};
相关文章推荐
- iOS多线程编程之Grand Central Dispatch(GCD)介绍和使用
- iOS 画音频波形曲线 根据音频数据版
- iOS本地通知的实现
- 适配iOS 9系统
- iOS 保持界面流畅的技巧
- iOS开发:应用生命周期
- iOS 调用系统自带的通讯录
- ios多线程初步研究
- iOS_ NSUserDefaults_数据本地化的轻型装备
- iOS 键盘自适应(IQKeyboardManager)使用小结
- iOS 开始
- iOS9的一些适配
- iOS9的一些适配
- iOS PCH文件
- iOS使用推送流程
- iOS, ViewControl的生命周期
- iOS中三种数据存储(本地持久化),cell是手写创建和stroyboard或者xib创建的初始化的方法
- IOS四种保存文件的方式
- iOS中tableView的三种刷新方法
- iOS中Quartz2D