------<a href="http://www.itheima.com" target="blank">Java培训、Android培训、iOS培训、.Net培训</a>、期待与您交流! -------
第一讲 block的基本概念
block的基本概念
Block对象是一个C级别的语法和运行机制。它与标准的C函数类似,不同之处在于,它除了有可执行代码以外,它还包含了与堆、栈内存绑定的变量。因此,Block对象包含着一组状态数据,这些数据在程序执行时用于对行为产生影响。
你可以用Block来写一些可以传到API中的函数语句,可选择性地存储,并可以使用多线程。作为一个回调,Block特别的有用,因为block既包含了回调期间的代码,又包含了执行期间需要的数据。
由于Objective-C 和 C++ 都是衍生自 C,block被设计为可同时兼容这三种语言。
你可以用Block来写一些可以传到API中的函数语句,可选择性地存储,并可以使用多线程。作为一个回调,Block特别的有用,因为block既包含了回调期间的代码,又包含了执行期间需要的数据。
由于Objective-C 和 C++ 都是衍生自 C,block被设计为可同时兼容这三种语言。
block的基本格式
用^操作符来声明一个Block变量,并指明Block述句的开始。Block的主体部分包含在{}内,像下图中一样(与C语法一样,“;”指明语句的结束):
/*
定义时,把block当成数据类型
特点:
1. 类型比函数定义多了一个^
2. 设置数值,有一个^,内容是{} 括起的一段代码
最简单的定义方式
void (^myBlock)() = ^ { // 代码实现; }
*/
void(^myBlock)() = ^ {
NSLog(@"hello");
};
// 执行时,把block当成函数
myBlock();block分为四种定义形式:
1)无参无返回值
2)无参有返回值 //和函数的定义有点相似,也是分成这四类
3)有参无返回值
4)有参有返回值
/*block带有参数的block的定义和使用
格式:
void (^block名称)(参数列表)
= ^ (参数列表) { // 代码实现; }
//定义有参数的block
void(^sumBlock)(int, int) = ^ (intx, inty) {
NSLog(@"%d", x + y);
};
//调用block
sumBlock(10, 20);
*//*带有参数和返回值的block
格式:
返回类型(^block名称)(参数列表)
= ^ 返回类型(参数列表) { // 代码实现; }
//定义有返回值和参数的block
int(^sumBlock2)(int, int) = ^ int(inta, intb) {
return a + b;
};
//调用有返回值的block
NSLog(@"%d", sumBlock2(4, 8));
*/第二讲 block的typedef
利用typedef定义block类型(和指向函数的指针很像)
/*格式:
typedef返回值类型(^block变量名)(参数类型列表);
typedefint(^MyBlock)(int,int);
typedef返回值类型(^block变量名)(参数类型列表);
以后就可以利用这种类型来定义block变量了。
*/
//给无参无返回值block变量起别名;
//格式:void (^新类型名)();
typedefvoid(^newType)();
//用新的类型定义block变量
newTypet1;
t1 =^{
NSLog(@"我是使用newType定义出来的变量t1的值");
};
//使用block
t1();第三讲 block访问外部变量
int m=10;
NSLog(@"m=%d",m);
NSLog(@"m addr=%p",%m); //在栈区
void(^myblock)()=^{
//m=100; 不可行
NSLog(@"m=%d",m);
NSLog(@"m addr=%p",&m); //在堆区
};
NSLog(@"m addr=%p",&m);
myblock();结论:当定义block的时候,block会把外部变量以cinst方式复制一份,不允许修改变量的值存放到block的所在内存中
int m=10;
void(^myblock)()=^{
int m=100; //定义一个新的变量,而不是修改m的值 存在栈区,相当于定义一个局部变量
NSLog(@"m addr=%p",&m);
}
myblock();
__block int m=10; //__block表示不在以const的方式拷贝
void(^myblock)(){
m=100; //之后再去使用m的时候,都变成是block内改变后的值,地址也在堆区
}MRC 环境
一、静态变量和全局变量 在加和不加__block 都会直接引用变量地址。也就意味着可以修改变量的值。在没有加__block 参数的情况下。
全局block 和栈block 区别为是否引用了外部变量,堆block 则是对栈block copy 得来。对全局block copy 不会有任何作用,返回的依然是全局block。
•
二,常量变量(NSString *a = @"hello";a 为常量变量,@“hello”为常量。)-----不加__block类型block 会引用常量的地址(浅拷贝)。加__block类型block会去引用常量变量(如:a变量,a = @"abc".可以任意修改a 指向的内容。)的地址。
如果不加__block 直接在block 内部修改变量,会编译报错。block 内部改变量是只读的。
但是就一定可以推断block 会深拷贝该变量吗???
对于常量@“hello”存储在内存中的常量区,程序结束才会释放内存。如:
NSString*str =@"hello";
NSString*abcStr =@"hello";
第四讲 block作为函数的返回值
步骤:
//使用typedef 定义一个新的类型
//给block起一个别名
typedefint(^newType)(intnum1,intnum2);
//使用新类型作为函数的返回值
//定义一个返回值是block类型的函数
newTypetest4(){
//定义一个newType 类型的block变量
newTypework1=^(intx,inty){
return x+y;
};
returnwork1;
}
//定定义变量接收函数返回的值(block类型)
//调用block
//在main函数中调用返回值是newType类型的函数
newTypent = test4();
NSLog(@"nt = %d",nt(45,23));
本文详细介绍了Block的基础概念,包括其作为数据类型的特点、四种定义形式以及如何使用Block作为函数参数和返回值。同时,文章讲解了Block如何访问外部变量,强调了__block关键字的作用。此外,还探讨了Block与栈、堆内存的关系以及在MRC环境下Block的使用注意事项。
2万+

被折叠的 条评论
为什么被折叠?



