android工程师开发IOS oc浅析(18)之block、typedef、block内部访问外部变量、block如何作为函数的参数

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的使用

  1. 定义新类型

语法: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代码的内部去修改,那么就在局部变量加上一个__block

    return0;

}

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;

}

猜你喜欢

转载自blog.csdn.net/qq_34476727/article/details/80498487