block
虽然很早就学习过block方面的知识,但一直没怎么用过,说明自己还是个菜鸟中的菜鸟,看到大牛们的代码优雅又简洁,各种炫酷的功能很多都有block的影子,所以下决心好好学习这方面的内容.以后有关于block中的所有问题都会总结在这里,方便加深对OC中block的理解。
block是一个数据类型
block是一个数据类型 所以可以声明一个block类型的变量
block类型的变量中专门存储一段代码,这段代码可以有参数和返回值
block变量的声明
格式: 返回类型(^block变量的名称)(参数列表);
例如:void (^myBlock1)(); 表示声明了一个block类型的变量叫做myBlock1 这个变量中只能存储没有返回值没有参数的代码段
int(^myBlock2)(int num1,int num2); 同理
注意:声明block变量的时候要指定这个block可以存储的代码段的返回值和参数描述,一旦指定,这个block就只能存储这样的代码段了,其他格式代码段无法存储.
初始化block
写一个符合block要求的代码段,存储到block变量中就可以
代码段格式
^返回值类型(参数列表){ 代码段; };
例如:^void(){ NSLog(@"I love you"); };
这是个无参无返回值的代码段
声明block变量的同时初始化
void (^myBlock)() = ^void() { NSLog(@"I love you"); };
执行代码段
myBlock();
block简写
没有返回值或参数,代码段的返回值void/参数()都可以省略,声明不可省略
void(^myBlock)() = ^{ NSLog(@"I love you"); };
声明block时候,如果有指定参数,声明的时候可以只写类型不写参数名称
int (^myBlock3)(int,int) = ^int(int num1,int num2) {int num3 = num1 + num2;return num3;};
无论代码段是否有返回值,在定义代码段的时候都可以省略.如果在写代码段的时候省略了返回类型,系统会自动确定返回值类型.
int(^myBlock4)(int,int) = ^(int num1,int num2) {int num3 = num1 + num2;return num3;
typedef
typedef是C中的关键字,它的主要作用是给一个数据类型定义一个新的名称,这些类型报告内部数据类型,比如int,char 还有自定义类型struct,enum等。
typedef一般有两个作用:(1) 给某种类型顶一个定义比较容易记的名字,相当于别名;(2)简化较为复杂的类型声明。
typedef的使用
- 定义新类型
语法:typedef 类型 新类型
#import <Foundation/Foundation.h>
typedef int newint;
typedef newint firstint;
int main(int argc, const char * argv[])
{@autoreleasepool {newint a=5;NSLog(@"%d",a);firstint b=19;NSLog(@"%d",b);}return 0;
}
typedef int newint 将类型int重新定义为newint类型,在后面的代码中我们可以看出使用 newint a=5; 这里出现了新的类型newint,而这个等价于int a=5。 继续看 typedef newint firstint 这里使用的newint定义一个新类型firstint。 在后面的代码中声明变量firstint b=19 同样通过,这个等价于newint b=19 等价于 int b=19 ,从上面可以看出他们之间是可以传递的。
函数指针
在使用到函数指针的时候,因为很多C方面的语法有欠缺,很多都是重新去查找资料温习,可能在某些地方还有错误。
语法: typedef 返回值类型 (*新类型) (参数列表)
int newfunc(int num){return num+100;
}int main(int argc, const char * argv[])
{@autoreleasepool {typedef int (*myfun)(int);myfun fun=newfunc;int value=(*fun)(100);NSLog(@"%d",value);}return 0;
}
上面的代码中定义了一个新的函数newfunc 其中返回值类型为int,有一个输入参数也是int。
在main方法中使用typedef 给函数newfunc定义了一个新的指针类型myfun。 然后这个类型指向了newfunc函数。
typedef 结构体和枚举
对比下面两段代码,看看使用typedef的struct和不使用typedef的struct的不同之处不使用typedef的struct
struct Student{int age;};struct Student stu ;stu.age=34;NSLog(@"%d",stu.age);
首先定义了一个Student 的struct 类型,如果要什么一个Student 的变量,必须使用struct Student stu,stu2 格式;
typedef struct Student{int age;} stu;stu a,b;a.age=45;b.age=32;NSLog(@"%d",a.age);
上面代码的作用就相当于给结构类型struct Student 指定了一个新名称 stu,所以在后面的使用的时候就不需要使用struct Student 可以直接使用stu即可。而使用enum 类型也是同样如此。
block内部访问外部变量
1).在block代码块的内部,可以取定义在外部的变量的值,定义在外部的局部变量和全局变量
2).在block代码块中可以修改全局变量的值,但是不能修改定义在外部的局部变量的值。(如果希望定义的的局部变量,可以允许block代码的内部去修改,那么就在局部变量加上一个__block)
#import <Foundation/Foundation.h>typedefvoid (^newType)();int num1 =100;int main(int argc,const char * argv[]) {__block int num2 = 200;newType block1 = ^{int num3 =300;num3++;NSLog(@"num = ===%d",num2);};block1();// 可以修饰num3和num1的值,但是不能修饰num2// 如果希望定义的的局部变量,可以允许block代码的内部去修改,那么就在局部变量加上一个__blockreturn0;}
block如何作为函数的参数
1.block是一个数据类型,所以可能可以作为参数
2.如何位函数定义block类型的参数:a.就是小括号中声明一个指定的block变量的就可以了,b.可以使用typedef简化定义,这样就简易了些
3,如何调用带block的参数呢?要求调用的时候,那么要调用的时候传入一个和形参block要求的代码段。调用的时候,可以先将代码段,存储到一个block变量中,然后传递这个block变量,也可以直接讲符合要求的代码段写到小括号里
4.将block作为函数的参数可以实现什么效果:可以将调用者自己写的1段代码,传递到 函数的内部区去执行.
#import <Foundation/Foundation.h>typedef void (^newType)();//为函数定义一个参数,定义个block类型的参数//无参数无返回值,//void test(void (^myBlock1)())void test(newType block1){NSLog(@"~~~~~~~");block1();NSLog(@"~~~~~~~~");}void test2 (int (^jiafaBlock)(int num1,int num2)){NSLog(@"~~~~~~~");int sum = jiafaBlock(100,200);NSLog(@"=====%d",sum);NSLog(@"~~~~~~~~");}int main(int argc, const char * argv[]) {newType type = ^{NSLog(@"哈哈");NSLog(@"呵呵");NSLog(@"嘿嘿");};test(type);test2(^int(int num1, int num2) {return num1 +num2;});// 调用的时候,可以先将代码段,存储到一个block变量中,然后传递这个block变量,也可以直接讲符合要求的代码段写到小括号中传递// test(^{
// NSLog(@"哈哈");// NSLog(@"呵呵");// NSLog(@"嘿嘿");// }// );return 0;}