OC块(Block)
Posted Billy Miracle
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了OC块(Block)相关的知识,希望对你有一定的参考价值。
什么是块
块是O-C对ANSI C所做的拓展,使用块可以更好地简化O-C编程,而且O-C的很多API都依赖于块。
块的基本语法
定义块的语法格式如下:
^ [块返回值类型] (形参类型1 形参1, 形参类型2 形参2, ...)
{
//块执行体
}
定义块的语法非常像定义一个函数,但只是定义一个匿名函数。
- 定义块必须以^开头。
- 定义块的返回值类型可以省略,且通常省略声明块的返回值类型。
- 定义块无需指定名字
- 如果块无返回值,块无须带参数,通常建议使用void作为占位符。
定义块变量的语法:
块返回值类型 (^块变量名) (形参类型1, 形参类型2, ...);
例:
#import <Foundation/Foundation.h>
int main(int argc , char * argv[]){
@autoreleasepool{
//定义不带参数,无返回值的块
void (^printStr) (void) = ^(void){
NSLog(@"我正在学习O-C的块");
};
//
double (^hypot)(double , double)= ^(double num1, double num2){
return sqrt(num1 * num1 + num2 * num2);
};
printStr();
//调用块,并输出返回值
NSLog(@"%g",hypot(3,4));
//也可以先只定义块变量:定义带参数、无返回值的块
void (^print)(NSString*);
//再将块赋给指定的块变量
print = ^(NSString* info){
NSLog(@"info参数为:%@" , info);
};
//调用块
print(@"学习块的知识");
}
}
程序不仅可以在定义块变量的同时对块变量赋值,也可以定义块变量,再对块变量赋值。
块变量与函数指针非常相似;而块则非常像一个匿名函数。当程序调用块时,调用块的语法与调用函数完全相同。从这个角度看,完全可以把块当成一种简化的函数。
编译、运行该程序,可以看到如下输出:
我正在学习O-C的块
5
info参数为:学习块的知识
块与局部变量
块可以访问程序中局部变量的值,当访问局部变量的值时,不允许修改局部变量的值。
#import<Foundation/Foundation.h>
int main (int argc, char * argv[]){
@autoreleasepool{
int my = 20;
void (^printMy)(void) = ^(void) {
//尝试对局部变量赋值,程序将会报错
//my = 30;
NSLog(@"%d" , my);
};
my = 45;
printMy();//调用块
}
}
运行结果是45
再看下一段程序,为局部变量增加__block修饰
#import<Foundation/Foundation.h>
int main (int argc, char * argv[]){
@autoreleasepool{
__block int my = 20;
void (^printMy)(void) = ^(void) {
//运行时访问、获取局部变量的值输出45
NSLog(@"%d" , my);
//尝试对局部变量赋值是允许的
my = 30;
NSLog(@"%d" , my);
};
my = 45;
printMy();//调用块
//由于块修改了__block局部变量的值,因此下面的代码输出30.
NSLog(@"块执行完后,my的值为:%d",my);
}
}
输出结果是:
45
30
30
说明已经修改了局部变量的值。
直接使用块作为参数
当把块作为方法参数时,无须定义块变量,直接把块作为参数传递给指定的方法即可,但块只能作为方法的最后一个参数。
使用typedef定义块变量类型
使用typedef可以定义块变量类型,一旦定义了块变量类型,则有两个主要用途:
- 复用块变量类型,重复定义多个变量
- 定义函数参数,可以定义带块参数的函数
示例:
#import<Foundation/Foundation.h>
int main(int argc , char * argv[]){
@autoreleasepool{
//使用typedef定义了块变量类型
typedef void (^FKPrintBlock)(NSString*);
//使用FKPrintBlock定义块变量,并将指定块赋给该变量
FKPrintBlock print = ^(NSString* info){
NSLog(@"%@" , info);
}
FKPrintBlock loopPrint = ^(NSString* info){
for (int i = 0; i < 3; i++){
NSLog(@"%@" , info);
}
};
//依次调用两个块
print(@"Objective-C");
loopPrint(@"ios");
}
}
此外,利用typedef定义的块变量类型即可为函数声明块变量类型的形参,这要求调用函数时必须传入块变量。
示例:
#import <Foundation/Foundation.h>
typedef void (^FKProcessBlock)(int);//定义一个块变量类型
//使用FKProcessBlock定义最后一个参数类型为块
void processArray(int array[] , unsigned int len, FKProcessBlock process){
for(int i = 0; i < len; ++i){
process(array[i]);//将数组元素作为参数调用块
}
}
int main(int argc , char * argv[]){
@autoreleasepool{
int arr[] = {2, 4, 6};//定义一个数组
//传入块作为参数调用processArray()函数
processArry(arr, 3, ^(int num){
NSLog(@"元素平方为:%d",num*num);
});
}
}
输出为:
元素平方为:4
元素平方为:16
元素平方为:36
以上是关于OC块(Block)的主要内容,如果未能解决你的问题,请参考以下文章