一.初识block
void (^testBlock)(void) = ^(){
//最基本的block
};
这就是一个最简单的block,为了方便初学者记忆理解,我们再来用熟悉的方法/函数来对比理解:如果方法/函数都不熟,我的朋友你路还有点长啊(- -!)
- (void)test{
//最基本的OC对象方法
}
- 第一个
void
:返回值,方法的返回值可以用什么这儿也可以用什么,方法的返回值是干啥的,这也是一样(如果还理解不了,留言我们交流一下)。 -
^
被称作"脱字符",难记的话你就记住:每次出现block的地方加个"尖尖"。 -
testBlock
block的变量名,类比方法的方法名,想咋写咋写。 -
(void)
block语法的参数列表。类比参数的参数列表。注意:iOS11之前没有参数写个()
就可以了。但是iOS11空参数类型需要写个void。否则系统会给你个黄色警告 -
= ^(){ //最基本的block };
这句话就是定义一个Block,给变量testBlock
赋值。同理,方法里能写啥这就可以写啥(有个注意点,我在下边描述)。
最基本的Block介绍完了,和方法一样我们在实际应用中肯定写这么个简单的玩意儿的,所以我贴一个稍微复杂点儿的定义Block代码(当然也就是个稍微了)
//func:拼接传入参数并返回
NSString* (^appendParameterBlock)(NSString* , int) = ^(NSString *name,int age){
NSMutableString *mutalStr = [NSMutableString string];
[mutalStr appendFormat:@"%@同学今年%d岁了",name,age];
return mutalStr;
};
二.如何定义Block
看完上边也就几十秒左右,你可能大概有个印象了。但是你可能现在默写一个Block还是有阻碍,这里我介绍两种方便又好记的方案
1.Xcode自带代码块inline
在写代码的地方写下inline
这个单词,会出现个索引,敲回车:
PS:类方法、对象方法中都行
//blockName :block的变量名。相当于int a;里边的a
<#returnType#>(^<#blockName#>)(<#parameterTypes#>) = ^(<#parameters#>) {
<#statements#>
};
看到没有,舒服又方便。这下你再对比上边的参数简介是不是印象又加深了一点。(作为Coder,上手写代码还是很重要的。初始Block的朋友我建议你敲一敲inline,效果更佳)。
2.别名typedef
在你写宏定义、#import的地方 写下typedefblock又会出现个索引,即:
//name :Block类型别名
typedef <#returnType#>(^<#name#>)(<#arguments#>); //索引
typedef void(^myBlock)(void); //示例
这样也可以通过起别名定义一个Block类型。
注意:
- typedef仅仅是为Block定义了一个别名。而在第一节里边写的name是变量名。这点必须认识清楚。
- 空参数列表,还是要写个void,同样也是系统的黄色警告。
- 帮助理解:
就拿上边那个最简单的Block来举例void (^testBlock)(void) = ^(){};
,这里block的类型就是void(^)(void)
,即空返回值空参数类型的block。你看这个东西就有点长,所以我们利用typedef来给他起个别名。这就是这个2用法的来源。(如果还是有疑问,留言我们交流一下)
三.使用Block
1. inline定义Block的使用
就用我们那个稍微稍微复杂的那个代码来举例使用
NSString *strPrint = appendParameterBlock(@"李华",13);
NSLog(@"%@",strPrint);
- 传入的参数类型及顺序须与定义时候的时候一致
2.别名typedef使用
说到起别名,我们经常使用的NSInteger
也其实是个long
类型的别名。(你可以点cmd+左键点击进去看下头文件看一下),既然我们起了个别名。 那我们就像用NSInteger一样使用嘛。看代码
//1.起别名
typedef void(^myBlock)(int a);
//2.定义或者叫创建一个变量
myBlock block = ^(int a ){
NSLog(@"%@",a);
};
//3.使用
myBlock(2);
//4.打印结果:2
四.Block的作用
上边我在介绍的时候就是用方法/函数来类比的。那么作用其实也一样,Block就是保存一段代码,然后再恰当的时候调用。
五.什么时候使用Block
- 用来传值。经典的就是两个页面之间的逆向传值。
- 请求网络数据(延迟),先把展示到控件的代码先保存到Block,等请求到数据的时候直接调用Block。经典的:AFNetworking
六.拓展:与代理delegate的比较理解
其实我们通常有一个说法:
-block相当于一个小弟,当我有这个小弟的时候,随叫随到,想让他干什么就干什么。再通俗点:小弟你帮我先把这段代码保存起来,等用户点击页面的时候,再让小弟去做这个事情就可以了。
- 代理delegate相当于打电话,通知你的代理人让他去做事情。
当然了上边是一个很不严谨的类比。本文只是为了让初学者更快掌握这个东西。暂且这样理解着。等掌握了之后,再查资料进行深入了解。
七.注意点
通过在.h文件定义一个block,我们来叙述一些注意点
#import <UIKit/UIKit.h>
typedef void(^PersonBlock)(int a);
@interface Person : NSObject
@property (nonatomic, copy) myBlock block;
@end
- 修饰block请用copy。想知道原因请点击修饰block为什么要用copy delegate要用weak,查看第六条。
- 定义block类型别名,我们约定:类名+block。当然你可以加上你block的功能描述单词。就好像我们约定OC命名用驼峰语法一样。
- block可以当做对象使用,但他不是一个对象。所以变量名前边不要加
*
号。 - 如果对象内部有一个Block属性,而在Block内部又访问了该对象,那么会造成循环引用。所以遇到问题请弱引用
__weak typeof(p) weakP = p;
本文旨在让初学者可以快速上手block,如果掌握以后并且想再深入理解,推荐一篇博客深入理解Block
网友评论