Objective-C——Block的使用

来源:互联网 发布:office免费安装包 mac 编辑:程序博客网 时间:2024/05/22 01:30

一. Block类型和函数指针的比较

1. 无参无返回值

(1). 先定义一个打印花的函数

void hua(){  printf(" {@}\n");  printf("  |\n");  printf(" \\|/\n");  printf("  |\n");}

(2). 比较

// a. 直接调用函数      hua();// b. 定义函数指针      void (*huaP)();      huaP = hua;      huaP();// c. 无参无返回值的Block运用      void (^huaB)();      huaB = ^{            printf(" {@}\n");            printf("  |\n");            printf(" \\|/\n");            printf("  |\n");          };      huaB();

2.有参无返回值

(1). 先定义一个有参函数

void sum(int a,int b){  printf("%d\n",a + b);}

(2).比较

// a.直接调用    sum(10, 10);// b.定义函数指针    void (*sumP)(int,int);    sumP = sum;    sumP(20,78);// c.有参无返回值的Block运用    void (^sumB)(int,int);    sumB = ^(int a,int b){           printf("%d\n",a + b);        };    sumB(12,33);

3.有参有返回值

(1).定义一个函数

int add(int a,int b){  return a + b;}

(2).比较

// a.直接调用    NSLog(@"%d", add(11,33));// b.定义函数指针    int (*addP)(int,int);    addP = add;    NSLog(@"%d", add(22,11));// c.有参有返回值的Block运用    int (^addB)(int,int);    //^int(int a,int b)中的反回值类型int可以省略    addB = ^(int a,int b){        return a + b;    };    NSLog(@"%d", addB(20,55));

二. 用typedef给Block声明新类型名

1. 定义函数

double multiply(double a,double b){  return  a * b;}

2. typedef声明新类型名

// (1).用typedef声明新的函数指针名字    typedef double (*newMultiply)(double,double);    newMultiply cheng = multiply;    NSLog(@"函数指针调用:%f",cheng(10.5,2.0));// (2).用typedef声明新的Block类型名字    typedef double (^blockMultiply)(double,double);    blockMultiply chengB = ^(double a,double b){      return a * b;    };    NSLog(@"调用Block:%f",chengB(5.5,2.0));

三. Block运用场景

当前后都有相同代码的的时候,只有中间的代码不一样时,可以考虑用Block变量

// 1. 用Block变量做函数参数void look(void (^lookB)()){  printf("起床\n");  printf("吃早晨\n");  lookB();  printf("吃晚餐\n");  printf("睡觉\n");}// 2. 定义Block变量    void (^lookB)() = ^{       printf("工作\n");    };// 3. 把定义好的Block传入函数    look(lookB);

四. Block代码块里面的变量和代码块外面的变量交互

1. BlocK里面的代码,可以使用外面的变量值

   int k = 10;    void (^block1)() = ^{      NSLog(@"%d",k);    };    block1();

2. BlocK里面的代码,不可以直接修改Block外面的变量,因为外面传进来的值是属于值传递,地址不一样。

    void (^block2)() = ^{      //k = 90;会报错。      NSLog(@"%d",k);    };    block2();

3. 在Block里面要修改Block外面的变量值,外面的变量声明时要加上__block

如果加上__block之后就是地址传递, 所以可以在block中修改外界变量的值

    __block int a = 80;    printf("%p\n",&a);    void (^block3)() = ^{      a = 100;      NSLog(@"%d",a);      printf("%p\n",&a);    };    block3();

五. 在Block里面使用对象

1. 当在Block里面使用对象,在复制Block变量时,对象引用计时器加1

    Person *person = [Person new];    NSLog(@"对象没有使用__block %ld",person.retainCount);    void (^perB)() = ^{      person.k = 100;      NSLog(@"对象没有使用__block %ld",person.retainCount);    };    Block_copy(perB);    perB();

2. 当对象使用__block声明,在Block里面使用对象,在复制Block变量时,对象引用计时器不加1

    __block Person *person1 = [Person new];    NSLog(@"对象使用__block %ld",person1.retainCount);    void (^perB1)() = ^{      person1.k = 100;      NSLog(@"对象使用__block %ld",person1.retainCount);    };    Block_copy(perB1);    perB1();

六. 面试题:block是存储在堆中还是栈中?

  1. 默认情况下block存储在栈中, 如果对block进行一个copy操作, block会转移到堆中。

  2. 如果block在栈中, block中访问了外界的对象, 那么不会对对象进行retain操作。

  3. 但是如果block在堆中, block中访问了外界的对象, 那么会对外界的对象进行一次retain。

  4. 如果在block中访问了外界的对象, 一定要给对象加上__block,只要加上了__block, 哪怕block在堆中, 也不会对外界的对象进行retain。
    如果是在ARC开发中就需要在前面加上__weak。

七. Block代码块的快捷键:inline Block

  <#returnType#>(^<#blockName#>)(<#parameterTypes#>) = ^(<#parameters#>) {    <#statements#>  };
0 0
原创粉丝点击