block的基本概念及基本用法
1.OC比C中多出的几个数据类型
SEL,id,BLOCK,BOOL,Boolean
2.BLOCK类型是一个C级别的语法和运行机制
3.Block的基本用法
block的typedef
用于给block起别名。
1.格式
typedef 返回值类型 (^新别名) (参数列表名);
typedef int(^myblock) (int,int);//此时的myblock不再是一个指针变量,而是一个类型,比如int,char。
例子:
int main(int argc,const char * argv[]){
autoreleasepool{
void (^myblock)() = ^{
NSLog(@"helloworld\n");
}
}
myblock();
typedef void (^block)();//定义了blcok类型,无参数无返回值
block b1;
b1 = ^{
NSLog(@"helloworld");
}
typedef int (^newtype1) (int,int);//定义了block类型,有参数有返回值
newtype nt1 = ^(int a,int b){
return a+b;
}
int s = nt1(12,23);
NSLog(@"s = %d",s);
}
block访问外部变量-------面试题
1.在block内部是否可以访问外部的变量
(1)block相当于一个对象,在堆区。编译的时候,系统会将外部变量(栈区)copy一份到block所属于堆区。
int main(int argc, const char * argv[]){
int m = 10;
NSLog(@"1:m = %d",m);
NSLog(@"2:m addr = %p",&m);//地址在栈区
void (^myblock)() = ^(){//创建block的时候,会将外部变量辅助一份放在block对象中,也就是在堆区
NSLog(@"5:m addr = %p");//地址在堆区
NSLog(@"3:in block m = %d");
}
NSLog(@"4:m addr = %p",&m);//地址栈区
myblock();
}
打印结果:
2:m addr = 0x7fff5fbff7bc
4:m addr = 0x7fff5fbff7bc
5:m addr = 0x100600180
注:堆区的后6位一般都有内容,而静态区(常量区)后四位有内容,从后四位往前四位都为0.而栈区的地址方位较长
(2)copy的时候,是以const的方式copy的方式copy进来的,所以在block内无法修改外部变量值
int main(int argc, const char * argv[]){
int m = 10;
NSLog(@"1:m = %d",m);
NSLog(@"2:m addr = %p",&m);//地址在栈区
void (^myblock)() = ^(){//创建block的时候,会将外部变量辅助一份放在block对象中,也就是在堆区
m =10;//编译的时候会报错,因为m是以const的方式copy进来的
NSLog(@"5:m addr = %p");//地址在堆区
NSLog(@"3:in block m = %d");
}
NSLog(@"4:m addr = %p",&m);//地址栈区
myblock();
}
(3)在block内部可以重新定义外部变量,并且该变量也会存放在栈区。
int main(int argc, const char * argv[]){
int m = 10;
NSLog(@"1:m = %d",m);
NSLog(@"2:m addr = %p",&m);//地址在栈区
void (^myblock)() = ^(){//创建block的时候,会将外部变量辅助一份放在block对象中,也就是在堆区
int m =100;//该m在栈区,因为创建的是局部变量
NSLog(@"5:m addr = %p");//地址在栈区
NSLog(@"3:in block m = %d");
}
NSLog(@"4:m addr = %p",&m);//地址栈区
myblock();
}
(4)如果必须在block内部修改外部变量的话,可以使用__block修饰变量。此时不再以const的方式copy
int main(int argc, const char * argv[]){
__block int m = 10;//使用block修饰,可以在block中修改m的值
NSLog(@"1:m = %d",m);
NSLog(@"2:m addr = %p",&m);//地址在栈区
void (^myblock)() = ^(){//此处copy的不再以const的方式copy的
m =100;//该m在堆区,因为创建的是局部变量
NSLog(@"5:m addr = %p");//地址在堆区
NSLog(@"3:in block m = %d");
}
myblock();
NSLog(@"4:m addr = %p",&m);//地址堆区,使用const修改的变量在block中被赋值后,之后使用的
// 该变量都是在堆区中取得。
}
注意:
1.blcok的分类
全局block:定义在函数外面的block是global类型的;另外,如果函数内部的block,但是没有捕获任何的自动变
量,那么他也是全局的
栈block:与全局block的区别为是否引用了外部变量(不懂)
堆bock:堆block则是对栈block copy得来,堆全局block copy不会有任何作用,返回的依然是全局block(不懂)
2.常量变量
常量变量(NSString *a = @"helllo";a为变量。@“hello”为常量)-----------不加__block类型的话,block会引用
常量的地址(浅拷贝)。加上__block类型的话,block回去引用常量变量(如:a是变量,a=@"abc",可以任意修
改a指向的内容)
如果不加__block,直接在block内部修改变量,编译会报错。block内部该变量是只读的。
block可以作为函数的返回值
1.步骤
(1)使用typedef定义一个新的类型
typedef void (^newtype)();
(2)使用新的类型作为函数的返回值
(3)定义block变量,接收函数返回值的结果
(4)执行block
例子:
typedef void (^newtype)();//使用typedef定义一个新的类型
newtype test(){//用新定义的类型作为函数的返回值
newtype w1 = ^(){
NSLog(@"xxxx");
NSLog(@"hello wlord");
}
return w1;//返回值block
}
typedef int (^newtype1)(int ,int );
newtype test1(){
return ^(int a,int b){
return a+b;
}
}
int main(int argc,const char * argv[]){
@autoreleasepool{
newtype n1 = test();//定义block变量接收函数返回值的结果。
n1();//执行函数
newtype1 n2 = test1();
int s = n2(23,12);
NSLog(@"s = %d",s);
}
return 0;
}
block的使用技巧及其注意事项
1.block助记符
输入inlineBlock,直接回车。block的格式模板会展现出来,可以按照这种方式修改。
2.自己写助记符
1.OC比C中多出的几个数据类型
SEL,id,BLOCK,BOOL,Boolean
2.BLOCK类型是一个C级别的语法和运行机制
3.Block的基本用法
block的typedef
用于给block起别名。
1.格式
typedef 返回值类型 (^新别名) (参数列表名);
typedef int(^myblock) (int,int);//此时的myblock不再是一个指针变量,而是一个类型,比如int,char。
例子:
int main(int argc,const char * argv[]){
autoreleasepool{
void (^myblock)() = ^{
NSLog(@"helloworld\n");
}
}
myblock();
typedef void (^block)();//定义了blcok类型,无参数无返回值
block b1;
b1 = ^{
NSLog(@"helloworld");
}
typedef int (^newtype1) (int,int);//定义了block类型,有参数有返回值
newtype nt1 = ^(int a,int b){
return a+b;
}
int s = nt1(12,23);
NSLog(@"s = %d",s);
}
block访问外部变量-------面试题
1.在block内部是否可以访问外部的变量
(1)block相当于一个对象,在堆区。编译的时候,系统会将外部变量(栈区)copy一份到block所属于堆区。
int main(int argc, const char * argv[]){
int m = 10;
NSLog(@"1:m = %d",m);
NSLog(@"2:m addr = %p",&m);//地址在栈区
void (^myblock)() = ^(){//创建block的时候,会将外部变量辅助一份放在block对象中,也就是在堆区
NSLog(@"5:m addr = %p");//地址在堆区
NSLog(@"3:in block m = %d");
}
NSLog(@"4:m addr = %p",&m);//地址栈区
myblock();
}
打印结果:
2:m addr = 0x7fff5fbff7bc
4:m addr = 0x7fff5fbff7bc
5:m addr = 0x100600180
注:堆区的后6位一般都有内容,而静态区(常量区)后四位有内容,从后四位往前四位都为0.而栈区的地址方位较长
(2)copy的时候,是以const的方式copy的方式copy进来的,所以在block内无法修改外部变量值
int main(int argc, const char * argv[]){
int m = 10;
NSLog(@"1:m = %d",m);
NSLog(@"2:m addr = %p",&m);//地址在栈区
void (^myblock)() = ^(){//创建block的时候,会将外部变量辅助一份放在block对象中,也就是在堆区
m =10;//编译的时候会报错,因为m是以const的方式copy进来的
NSLog(@"5:m addr = %p");//地址在堆区
NSLog(@"3:in block m = %d");
}
NSLog(@"4:m addr = %p",&m);//地址栈区
myblock();
}
(3)在block内部可以重新定义外部变量,并且该变量也会存放在栈区。
int main(int argc, const char * argv[]){
int m = 10;
NSLog(@"1:m = %d",m);
NSLog(@"2:m addr = %p",&m);//地址在栈区
void (^myblock)() = ^(){//创建block的时候,会将外部变量辅助一份放在block对象中,也就是在堆区
int m =100;//该m在栈区,因为创建的是局部变量
NSLog(@"5:m addr = %p");//地址在栈区
NSLog(@"3:in block m = %d");
}
NSLog(@"4:m addr = %p",&m);//地址栈区
myblock();
}
(4)如果必须在block内部修改外部变量的话,可以使用__block修饰变量。此时不再以const的方式copy
int main(int argc, const char * argv[]){
__block int m = 10;//使用block修饰,可以在block中修改m的值
NSLog(@"1:m = %d",m);
NSLog(@"2:m addr = %p",&m);//地址在栈区
void (^myblock)() = ^(){//此处copy的不再以const的方式copy的
m =100;//该m在堆区,因为创建的是局部变量
NSLog(@"5:m addr = %p");//地址在堆区
NSLog(@"3:in block m = %d");
}
myblock();
NSLog(@"4:m addr = %p",&m);//地址堆区,使用const修改的变量在block中被赋值后,之后使用的
// 该变量都是在堆区中取得。
}
注意:
1.blcok的分类
全局block:定义在函数外面的block是global类型的;另外,如果函数内部的block,但是没有捕获任何的自动变
量,那么他也是全局的
栈block:与全局block的区别为是否引用了外部变量(不懂)
堆bock:堆block则是对栈block copy得来,堆全局block copy不会有任何作用,返回的依然是全局block(不懂)
2.常量变量
常量变量(NSString *a = @"helllo";a为变量。@“hello”为常量)-----------不加__block类型的话,block会引用
常量的地址(浅拷贝)。加上__block类型的话,block回去引用常量变量(如:a是变量,a=@"abc",可以任意修
改a指向的内容)
如果不加__block,直接在block内部修改变量,编译会报错。block内部该变量是只读的。
block可以作为函数的返回值
1.步骤
(1)使用typedef定义一个新的类型
typedef void (^newtype)();
(2)使用新的类型作为函数的返回值
(3)定义block变量,接收函数返回值的结果
(4)执行block
例子:
typedef void (^newtype)();//使用typedef定义一个新的类型
newtype test(){//用新定义的类型作为函数的返回值
newtype w1 = ^(){
NSLog(@"xxxx");
NSLog(@"hello wlord");
}
return w1;//返回值block
}
typedef int (^newtype1)(int ,int );
newtype test1(){
return ^(int a,int b){
return a+b;
}
}
int main(int argc,const char * argv[]){
@autoreleasepool{
newtype n1 = test();//定义block变量接收函数返回值的结果。
n1();//执行函数
newtype1 n2 = test1();
int s = n2(23,12);
NSLog(@"s = %d",s);
}
return 0;
}
block的使用技巧及其注意事项
1.block助记符
输入inlineBlock,直接回车。block的格式模板会展现出来,可以按照这种方式修改。
2.自己写助记符