iOS开发--当Block、代理、通知遇到女朋友

什么是Block?

为什么使用Block?

怎么使用Block?

本文将从这三个问题入手来逐渐了解Block。

本文使用的范例传送门:https://github.com/Elbertz/ZDXBlockStudy


什么是Block?

首先我们先来观察一下block的书写格式

a (^b)(c,d)=^(c name1,d name2){};

a:Block的返回值类型,可以为空(void);

b:Block对象名称,可以理解为变量名;

^:块的语法标记,声明b为一个Block对象;

c:第一个参数类型

d:第二个参数类型

name1,name2:参数名;

{}:Block代码块的主题部分。

有人认为Block是代码块,以闭包形式存在的一段代码良好的独立性和可交互性;

也有人把Block当作OC的匿名函数,可以很好的传递参数;

还有人认为Block是一种特殊的数据类型,创建的Block对象可以更好的被上下文所调用;

还有一群人,他们觉得Block就是Block,盲目而片面的定义掩盖了它简易精妙的使用,因此他们从使用场景中描述Block是什么。

为什么使用Block?

Block作为参数、返回值可以更便捷的在各个场景间传递;

Block作为回调可以广泛的使用在多线程GCD、动画、排序的情形下;

下面是Block的基础使用,对Block的使用思路清晰的童鞋可以通过下面的2个案例进行深度学习:

Block实现各种排序:https://github.com/JiongXing/JXSort

AFNetworking:https://github.com/AFNetworking/AFNetworking

怎么使用Block?

在使用之前,我们先对Block在ARC和MRC环境下使用的基础知识点普及:

ARC:系统会帮你管理你自己创建的对象的内存

MRC:你需要管理你自己创建的对象的内存

当你创建一个新的project时默认是ARC环境,你可以在Build Setting下关闭自动引用记数切换到MRC环境。

为什么使用copy来修饰Block?

使用copy可以将Block从栈上转移到堆上

MRC下,默认是栈上为了控制Block生命周期,需要将其copy的堆上,不可以用reatin代替。 ARC下大多数情况默认是在堆上,但是因为一般遵循传统,会写上copy,但是可以用strong来代替。

ARC下需不需要对Block进行手动copy?

不用手动copy的情形?

1.当 Block 被强引用时。

2.系统的 API 中带有 usingBlock 时。

3.Block 作为函数返回值。

用手动copy的情形?

当block 作为函数参数的时候,在 arc 下我们自定义的Block 要写上 copy。

注意:copy的特点

1.如果原来在栈上,通过copy,被复制到堆上。

2.如果原来在全局数据区,不会发生改变

3.如果在堆区:其引用计数加1

在Block使用过程中,如何避免循环引用?

ARC情况下

1.如果用copy修饰Block,该Block就会存储在堆空间。则会对Block的内部对象进行强引用,导致循环引用。内存无法释放。

2.如果用weak修饰Block,该Block就会存放在栈空间。不会出现循环引用问题。

MRC情况下

用copy修饰后,如果要在Block内部使用对象,则需要进行(__block typeof(Target) blockTarget = Target )处理。在Block里面用blockTarget进行操作。

__block在MRC下有两个作用

1. 允许在Block中访问和修改局部变量

2. 禁止Block对所引用的对象进行隐式retain操作

__block在ARC下只有一个作用

1. 允许在Block中访问和修改局部变量

__weak可以避免在ARC下Block造成循环引用

使用场景?

标准范式:

// 1.使用typedef定义Block类型

typedef int(^MyBlock)(int, int);

// 2.定义一个形参为Block的OC函数

- (void)useBlockForOC:(MyBlock)aBlock

{

NSLog(@"result = %d", aBlock(300,200));

}

// 3.声明并赋值定义一个Block变量

MyBlock addBlock = ^(int x, int y){

return x+y;

};

// 4.以Block作为函数参数,把Block像对象一样传递

[self useBlockForOC:addBlock];

// 将第3点和第4点合并一起,以内联定义的Block作为函数参数

[self useBlockForOC:^(int x, int y){

return x+y;

}];

情景一:传递参数

viewController 控制器1,testViewController 控制器2,控制器1跳转到控制器2,然后在控制器2触发事件回调修改控制器1的对应控件的背景色为红色?

testViewController

typedef void (^myBlock)(UIColor* color);

@property (nonatomic,copy)myBlock block1;

UIColor *color = [UIColor redColor];

//给Block传入参数color

self.block1(color);

[self.navigationController popViewControllerAnimated:YES];

viewController

//plan1

testViewController *testVC = [[testViewController alloc]init];

testVC.block1 = ^(UIColor *color){

label1.backgroundColor = color;

};

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

//plan2

//当block中使用了self时,需要对self添加__weak关键字,避免循环调用

__weak typeof(self) weakself = self;//等价于下一行代码

//__weak UIViewController* weakself = self;

testViewController *testVC = [[testViewController alloc]init];

testVC.block1 = ^(UIColor *color){

weakself.label2.backgroundColor = color;

};

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

当在Block代码块中使用了self,请注意要避免循环应用。

Q:说好的女朋友呢? 看好了,女朋友的问题来了

一天,你的女朋友逛淘宝的时候对你说,这个包包好漂亮,买给我嘛?么么哒! 面对糖衣炮弹轰击对你默默的登录了自己的支付宝账号点下了确认支付的按钮。

女朋友想买的东西委托给你去买,这是代理模式的典型案例,同样也可用block实现。

1)代理模式实现

girlFriends *gf = [girlFriends shareInstance];

gf.delegate = self;

[gf buyALadiesBackpackForMe];

2)使用Block实现

__weak typeof(self) weakself = self;

//block先赋值,再使用

girlFriends *gf = [girlFriends shareInstance];

//[gf buyAnotherLadiesBackpackForMe]; //wrong write place

gf.buyBlock = ^(NSString *goods){

NSString *tempStr = [NSString stringWithFormat:@"%@❤️❤️❤️",goods];

[weakself.label4 setText:tempStr];

};

[gf buyAnotherLadiesBackpackForMe];

if (timer.isValid == YES) {

[timer invalidate];

}

3.使用通知模式实现

//tips:先注册观察者,再发送通知

girlFriends *gf = [girlFriends shareInstance];

//[gf buyAnyoneLadiesBackpackForMe];

[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(buyLVAction:) name:@"buybag" object:nil];

[gf buyAnyoneLadiesBackpackForMe];

-(void)dealloc{

//记得释放通知的观察者对象

[[NSNotificationCenter defaultCenter] removeObserver:self name:@"buybag" object:nil];

}

情景二:Block作为参数

girlFriends *gf = [girlFriends shareInstance];

[gf buyMoreLadiesBackpackForMe:^float(int loveNumber) {

//

NSLog(@"520");

float result = 520+(float)loveNumber/10000;

NSLog(@"%.4f",(float)loveNumber/10000);

NSString *tempStr = [NSString stringWithFormat:@"%.4f❤️❤️❤️",result];

[_label6 setText:tempStr];

return result;

}];

if (timer.isValid == YES) {

[timer invalidate];

}

girlFriends.m

-(void)buyMoreLadiesBackpackForMe:(myLoveBlock2)ablock{

float result = ablock(1314);

NSLog(@"%.4f",result);

}

情景三:Block作为返回值

通过递归调用来体现以Block作为返回值的函数的调用和实现

调用

[self digui:3];

实现

- (int)digui:(int)number{

if (number <= 2 && number > 0) {

return number;

} else {

int tempResult = [self digui:number-1];

return number*tempResult;

}

}

调用

gf.setupTab5(3);

实现

- (int(^)(int))setupTab5

{

__weak typeof (self)weakSelf = self;

int(^block)(int) = ^(int a){

_recursiveResult2 *= a;

NSLog(@”%d – %d”, _recursiveResult2,a);

if (a>1) {

weakSelf.setupTab5(a-1);

//weakSelf setupTab5;

}

return _recursiveResult2;

};

return block;

}

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

推荐阅读更多精彩内容

  • 《Objective-C高级编程》这本书就讲了三个东西:自动引用计数、block、GCD,偏向于从原理上对这些内容...
    WeiHing阅读 9,733评论 10 69
  • Block使用场景,可以在两个界面的传值,也可以对代码封装作为参数的传递等。用过GCD就知道Block的精妙之处。...
    Coder_JMicheal阅读 696评论 2 1
  • 前言 Blocks是C语言的扩充功能,而Apple 在OS X Snow Leopard 和 iOS 4中引入了这...
    小人不才阅读 3,729评论 0 23
  • Block简介(copy一段) Block作为C语言的扩展,并不是高新技术,和其他语言的闭包或lambda表达式是...
    qui丶MyLove阅读 367评论 0 0
  • 在2015年5月21日凌晨梦到这个故事的开头,当时五点半爬起来把开头写下,只是直到现在才开始动手想着把它补成一个小...
    珊瑚赫阅读 1,205评论 0 1