您的位置:首页 > 职场人生

黑马程序员——block的概念及其基本使用

2015-11-22 23:36 766 查看
------<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的基本格式
       用^操作符来声明一个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的使用技巧:有个助记符 inlinrblock 可以提取系统的block的格式
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: