OC高级特性--Block匿名函数

原创 2015年07月06日 19:36:53

块是Objective-C语言提供的一个强大特性,博主会介绍块语法的意义、块内存管理、怎样在程序中开发块和怎样使用现有API(如Foundation框架)中的块。
简言之,块提供了一种方式,使用这种方式可以创建一组语句(即代码块)并将这些语句赋予一个变量,随后就可以调用这个变量。从这方面看,块与函数方法类似,但除了是可执行代码外,块还含有与堆内存和栈内存绑定的变量。块就是一个实现的闭包(closure),一个允许访问其常规范围之外变量的函数。此外,一个Objective-C块实际上就是一个对象;一个NSObject类的子类,拥有NSObject类的所有相关属性(如可以向块发送消息)。

1.块的语法

在学习使用块编写的过程中,难点之一是掌握块的语法。本段内容详解介绍块语法,并且会通过示例展示块在代码中的作用。
块类型由返回值类型和参数类型列表构成。使用脱字符(^)可以声明块类型的变量。
声明块类型的语法

也许这张图片看客们还不能让各位看客去和C语言的函数做类比记忆,博主带着大家将Block的定义和函数指针类型做对比记忆。

//1.sum函数声明
函数声明:int sum(int a, int b);
函数类型int(int, int);
函数指针类型:int(*)(int, int);
将函数指针类型重命名:typedef int(*FUNP)(int, int);
//2.Block声明
注意:这里只要将函数指针类型标志"*"改为Block语法的标志"^"就是Block语法。
int (^sum)(int, int)
上面博主已经介绍过了,Block是将一个函数的实现赋予Block变量,下面定义函数。
//3.函数定义语法
int sum(int a, int b) {
    return a + b;
}
//4.Block定义
把前面的Block变量类型拿过来
int (^sum)(int, int)
将函数的定义赋给Block变量sum
int (^sum)(int, int) = ^int (int a, int b) {
    return a + b;
}

注意:
1.后面的函数实现的名字被去掉了,这里赋给Block变量的其实是一个匿名函数。
2.等号右面加了一个Block语法标志”^”不能省略。
这样一个Block语法块、或者叫做匿名函数就创建好了


1.块常量表达式—-没有设置返回值类型的块常量表达式

^int (int addend) {
retutn addend + 1;
}

无需再块定义中为这个块设置返回值类型,因为编译器会从块主题中的return语句推断出返回值的数据类型。
2.不带参数的块常量定义

^ {
NSLog(@"Hello,World!");
}

块语法元素的比较

块语法元素 块变量声明 块常量表达式
脱字符 标识一个块变量声明的开始。脱字符位于变量名称之前,两者都被封装在圆括号中 标识一个块变量表达式的开始
名称 块变量的名称是必选项 块常量表达式没有名称
返回值类型 在块变量声明中返回值类型是必选项。没有返回值的块变量会将返回值声明为void 从块表达式的语句主题推断出返回值类型。如果块表达式的语句主题中有一个以上的return语句,那么他们的返回值必须为同一类
参数 在块变量声明中,参数类型列表是必选项。如果块变量没有参数,必须将参数类型列表声明为void 在块常量表达式中,参数列表是可选项

2.块就是闭包

如前面所述,块就是一个实现的闭包,就是一个允许访问在其常规范围外部声明的局部变量的函数。为了理解这些概念,让我们先来了解范围和可见性规则。变量的可见性是指变量在程序的哪个(些)部分中可以被访问,这也称为变量的范围。例如,在C语言函数定义中声明的变量拥有局部范围,这意味着这些变量仅仅在该函数中是可见的和可访问的(注意,函数还可以引用全局变量)。与C语言函数相比,块参数通过以下特性提高了变量的可见性。

  • 对词汇范围的支持:这是从封闭范围引用局部变量和参数的特性。
  • __block变量:__block关键字可以应用于块外部但仍处于同一词汇范围外的变量。通过该特性可以修改块内部的变量。
  • 访问实例变量:在对象的方法实现代码中定义的块可以访问该对象中的实例变量。
  • 导入参数 :通过头文件(通过#improt或#include指令)导入的常数变量在块常量表达式中是可见的。

2.1词汇范围

块的一大特性就是支持词汇范围。与之相反,C语言函数无法访问在其定义外部声明的局部变量。

void logValue() {
//错误,对变量myVar进行了非法访问,该变量不在访问范围内
    NSLog(@"Variable value %d", myVar);
}
int main(int argc, const char *argv[]) {
    int myVar = 10;
    logValue();

    return 0;
}

块支持词汇范围,因此块常量表达式可以访问在同一词汇范围内声明的变量。此外,一方面,能够定义变量的地方就能够定义块,例如,在函数、方法和其他块中都可以定义块。另一方面、C语言函数无法在其他函数和方法中定义。以下代码可以成功编译和运行,因为变量myVar是在logValueBlock块所在的词汇范围内声明的。

{
    int myVar = 10;
    void (^logValueBlock)(void) = ^{
        NSLog(@"Variable value = %d", myVar);
    };
    logValueBlock();
}

如以上代码所示,一个块访问了在其定义之外声明的局部变量。尤其是,这些局部变量是在声明块常量表达式之前,在一个封闭范围内被声明(和初始化)的。可以用花括号划定局部范围,此外,还可以嵌套捍卫。一方面,如上面代码所示,变量myVar是定义logValueBlock块的范围内被声明的,而且其声明位于块常量表达式之前,因为可以在这个块常量表达式中使用。另一方面,如果局部变量myVar是在块常量表达式之后声明和初始化的,则块对局部变量的访问是非法的。

{
    int myVar = 10;
    void (^logValueBlock)(void) = ^{
        //错误,词汇范围变量无法重新赋值
        myVar = 5;
        NSLog(@"Variable value = %d", myVar);
    };
    logValueBlock();
} 

2.2可以修改的__block变量

默认情况下,在块常量表达式中通过词汇范围访问的块局部变量不能修改。使用存储类型修改符__block可以将这些变量切换为读写模式(可以修改)。除了C语言的变长数组(不是由常量表达式表示长度的数组)和含有变长数组的C语言结构之外,可以对Objective-C支持的所有类型使用__block修改符。__block修改符不能与局部变量存储修改符auto、register和static组合使用。

__block int myVar = 10;
void(^incBlock)(int) = ^(int amount) {
    myVar += amount;
    NSLog(@"New value = %d", myVar);
};
incBlock(5);

当引用变量的块被赋值到堆存储区域时,使用__block修饰符的变量也会被复制到堆存储区域。这个本博客最后的知识点因除了内存管理的话题,下面将介绍该内容。

iOS开发 多视角抛析匿名函数—— Block

在iOS开发中Block的使用随处可见,使用场景也非常多,例如在网络中进行网络请求的回调,通过Block实现逆传,封装复杂业务逻辑等等,总之Block是带有自动变量的匿名函数,在iOS开发中,能灵活掌...

关于OC中的Block,Swift中的闭包,C++11中的lambda表达式等匿名函数详解

Hello,大家好啊!逗比老师又来给大家逗比啦!今天咱们逗比的内容,就来围绕一个比较棘手的问题——匿名函数。我有一个朋友在学习做iOS开发,他最近就在被这个Block缠绕弥漫,感觉云里雾里,所以希望我...

iOS经典讲解之Swift匿名函数(闭包)(二)

作者:Loving_iOS 转载请标明出处:http://blog.csdn.net/loving_ios/article/details/49365785 本次讲解的开发环境为Xcode7.0.1 ...

C语言中闭包的探究及比较

这是一篇技术分享,并且之前发表在酷壳上,http://coolshell.cn/articles/8309.html,现在发布到自己的博客上。 下文是直接从酷客复制过来的,这里偷了个懒,没有再次对格...

通过Xcode将项目同步到GitHub上

主要参考这篇文章:http://www.mindthe.net/devices/2011/04/28/12-steps-to-using-github-with-xcode-4/ 1. 在Xcode...

Objective-C学习笔记(十)——循环语句for和do-while的使用

在OC中,除了while这种循环方式外,还有另外for循环和do-while循环,它们在不同的业务逻辑下会有不同的作用。可以和C语言和Java对比着学习。 (一)代码一: int main(int a...

Block剧终:Objective-C中的闭包性和匿名函数

目录 1、关于     1.1匿名函数     1.2闭包性 2、Objective-C中的实现     2.1将block当做参数来传递     2.2闭包性     2.3内...

iOS开发学习第十九课——匿名函数 Block

//Block的定义:Block也是一个函数,称为一个语法块(实现某个特定功能),只不过Block是一个比较特殊的函数,没有函数名称的函数,又叫做匿名函数 格式: 返回值类型 (^Bloc...

Block剧终:Objective-C中的闭包性和匿名函数

Block剧终:Objective-C中的闭包性和匿名函数 blocks-1024x576 本文由破船译自xs-labs转载请注明出处! 小引 还记得昨天我给大家推荐的文章...

块语法 Block 本质上是匿名函数(没有名称函数)

/*Block 块语法 本质上是匿名函数(没有名称函数) 标准C里面没有匿名函数,在C语言后期版本中加入了匿名函数  在c++ 、 js 、 swift有类似语法,叫做闭包  block 和函数指...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:OC高级特性--Block匿名函数
举报原因:
原因补充:

(最多只允许输入30个字)