block的使用和注意

                         iOS学习-(1)block的使用和注意

本文简介

本文主要介绍1.block的基本使用 2.block使用中的注意(循环引用)

Block简介

代码块Block是苹果在iOS4开始引入的对C语言的扩展,用来实现匿名函数的特性。

Block是一种比较特殊的数据类型。和int float 类型一样是一种数据类型,其可以正常定义变量、作为参数、作为返回值,等  但是,特殊地,它可以保持一段代码,在合适的时候取出来调用,也就是存储了一个指向保持代码的地址,因此它可以像指针一样copy保持的一段代码。因此总结block 形式如int普通类型,但是实际作用更像指针。

目前Block已经广泛应用于iOS开发中,常用于GCD、动画、排序及各类回调。

现在我们主要用的就是他的各类回调(页面传值)

//动画([UIView animateWithDuration:0.3 animations:^{)

}];


注: Block的声明与赋值只是保存了一段代码段,必须调用才能执行内部代码

block的定义和使用

block 定义 

返回值类型(^block变量名)(形参列表) = ^(形参列表) {

};

调用Block保存的代码

block变量名(实参);

因为Block 保存的是一段代码 所以有返回值和形参列表就很正常了

使用typedef定义Block类型

在实际使用Block的过程中,我们可能需要重复地声明多个相同返回值相同参数列表的Block变量,如果总是重复地编写一长串代码来声明变量会非常繁琐,所以我们可以使用typedef来定义Block类型

// 定义一种无返回值无参数列表的Block类型

typedef void(^SayHello)();

// 我们可以像OC中声明变量一样使用Block类型SayHello来声明变量

SayHello hello = ^(){

NSLog(@"hello");

};

// 调用后控制台输出"hello"

hello();

Block的模式

1.无参数无返回值的Block

2.有参数无返回值的Block

3.有参数有返回值的Block

Block简单用法举例

无参数无返回值的Block

/**

*  无参数无返回值的Block

*/

-(void)func1{

/**

*  void :就是无返回值

*  emptyBlock:就是该block的名字

*  ():这里相当于放参数。由于这里是无参数,所以就什么都不写

*/

void (^emptyBlock)() = ^(){

NSLog(@"无参数,无返回值的Block");

};

emptyBlock();

}

有参数无返回值的Block

/**

*  调用这个block进行两个参数相加

*

*  @param int 参数A

*  @param int 参数B

*

*  @return 无返回值

*/

void (^sumBlock)(int ,int ) = ^(int a,int b){

NSLog(@"%d + %d = %d",a,b,a+b);

};

/**

*  调用这个sumBlock的Block,得到的结果是20

*/

sumBlock(10,10);

有参数有返回值的Block

/**

*  有参数有返回值

*

*  @param NSString 字符串1

*  @param NSString 字符串2

*

*  @return 返回拼接好的字符串3

*/

NSString* (^logBlock)(NSString *,NSString *) = ^(NSString * str1,NSString *str2){

return [NSString stringWithFormat:@"%@%@",str1,str2];

};

//调用logBlock,输出的是 我是Block

NSLog(@"%@", logBlock(@"我是",@"Block"));

示例

Block结合typedef使用自己定义一个Block类型,用定义的类型去创建Block,更加简单便捷。这里举例一个Block回调修改上一下界面的背景颜色。ViewController1 控制器1,ViewController2 控制器2控制器1跳转到控制器2,然后在控制器2触发事件回调修改控制器1的背景颜色为红色。

ViewController2的实现

#import@interface ViewController2 : UIViewController

/**

*  定义了一个changeColor的Block。这个changeColor必须带一个参数,这个参数的类型必须为id类型的

*  无返回值

*  @param id

*/

typedef void(^changeColor)(id);

/**

*  用上面定义的changeColor声明一个Block,声明的这个Block必须遵守声明的要求。

*/

@property (nonatomic, copy) changeColor backgroundColor;

@end

-(void)touchesBegan:(NSSet*)touches withEvent:(UIEvent *)event{

//声明一个颜色

UIColor *color = [UIColor redColor];

//用刚刚声明的那个Block去回调修改上一界面的背景色

self.backgroundColor(color);

}

ViewController1的实现

-(void)touchesBegan:(NSSet*)touches withEvent:(UIEvent *)event{

ViewController2 *vc =[[ViewController2 alloc]init];

// 回调修改颜色

vc.backgroundColor = ^(UIColor *color){

self.view.backgroundColor = color;

};

[self.navigationController pushViewController:vc animated:YES];

}

Block注意 (循环引用)

//需要明白的

1.ARC中声明的局部变量的对象是一个强引用

2.对象消亡的条件是没有一个强引用指向这个对象

3.对象没有强引用,不会马上消亡

结论:

1.如果在^(){

block内部 引用了在外部声明的强引用【对象A】,则在block内部自动对产生一个强引用来指向【对象A】

block内部 引用了在外部声明的弱引用【对象A】,则在block内部自动对产生一个弱引用来指向【对象A】

如果嵌套的block的最里面的block 有引用最外部的强引用【对象A】,则有通透现象发生,所有外部的Block也都有强引用指向该【对象A】


};


实现方法

如果B对象有强引用A对象,而对象A 有属性(copy)block,如果对象B在A中的Block被强引用,则导致导致A和B循环引用,进而引起内存泄漏,一般在block内应用的对象 都要在外部声明一个弱引用

mTopView = [[BBSTopButtonView alloc]initWithFrame:CGRectMake(0, 0, kScreenWidth, 45) configDic:nil];

__weak SwimmerBBSViewController *weakSelf = self;

mTopView.block = ^(NSInteger type) {

if (type == 100) {

mType = 8888;

weakSelf.mTableView.hidden = YES;

weakSelf.mCollectionView.hidden = NO;

}else{

mType = type-100;

weakSelf.mTableView.hidden = NO;

weakSelf.mCollectionView.hidden = YES;

}

mPage = 1;

[weakSelf getData];

};

[self.view addSubview:mTopView];

分析:

和实现方法对应:

 self为B对象

 mTopView 为self中的全局变量 (强引用)A对象


循环引用比较简单,造成循环引用的原因无非就是对象和block相互强引用,造成谁都不能释放,从而造成了内存泄漏。基本的一些例子我就不再重复了,网上很多,也比较简单,我就一个问题来讨论下,也是开发中有人问过我的一个问题:

block里面使用self会造成循环引用吗?

很显然答案不都是,有些情况下是可以直接使用self的,比如调用系统的方法:

1

2

3

[UIView animateWithDuration:0.5 animations:^{

NSLog(@"%@", self);

}];

因为这个block存在于静态方法中,虽然block对self强引用着,但是self却不持有这个静态方法,所以完全可以在block内部使用self。

还有一种情况:

当block不是self的属性时,self并不持有这个block,所以也不存在循环引用

1

2

3

4

void(^block)(void) = ^() {

NSLog(@"%@", self);

};

block();

只要我们抓住循环引用的本质,就不难理解这些东西。







最后附上巧神对Block底层源码实现的讲解,讲的很透彻,分析的很好!



参考文献

iOS中Block的基础用法

一篇文章看懂iOS代码块Block

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,921评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,635评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,393评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,836评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,833评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,685评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,043评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,694评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 42,671评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,670评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,779评论 1 332
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,424评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,027评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,984评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,214评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,108评论 2 351
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,517评论 2 343

推荐阅读更多精彩内容

  • block.png iOS代码块Block 概述 代码块Block是苹果在iOS4开始引入的对C语言的扩展,用来实...
    全栈农民工阅读 588评论 0 1
  • Lua 5.1 参考手册 by Roberto Ierusalimschy, Luiz Henrique de F...
    苏黎九歌阅读 13,733评论 0 38
  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,598评论 18 139
  • 《Objective-C高级编程》这本书就讲了三个东西:自动引用计数、block、GCD,偏向于从原理上对这些内容...
    WeiHing阅读 9,793评论 10 69
  • 目录 Block概述 Block定义方式 Block保存代码 Block传值 Block对外部变量的传递 Bloc...
    子斌阅读 1,386评论 2 7