zoukankan      html  css  js  c++  java
  • Objective-C之Block

    Block基本概念

    本小节知识点:

    1. 【了解】什么是Block
    2. 【理解】block的格式

    1.什么是Block

    • Block是iOS中一种比较特殊的数据类型

    • Block是苹果官方特别推荐使用的数据类型, 应用场景比较广泛

      • 动画
      • 多线程
      • 集合遍历
      • 网络请求回调
    • Block的作用

      • 用来保存某一段代码, 可以在恰当的时间再取出来调用
      • 功能类似于函数和方法

    2.block的格式

    • Block的定义格式
    返回值类型 (^block变量名)(形参列表) = ^(形参列表) {
    
    };

    • block最简单形式
    void (^block名)() = ^{代码块;}
    
    例如:
    void (^myBlock)() = ^{ NSLog(@"李南江"); };
    • block带有参数的block的定义和赋值
    void (^block名称)(参数列表)
    = ^ (参数列表) { // 代码实现; }
    
    例如:
    void (^myBlock)(int) = ^(int num){ NSLog(@"num = %i", num); };
    • 带有参数和返回值的block
    返回类型 (^block名称)(参数列表)
    = ^ (参数列表) { // 代码实现; }
    
    例如:
    int (^myBlock)(int, int) = ^(int num1, int num2){ return num1 + num2; };
    • 调用Block保存的代码
    block变量名(实参);

    block和typedef的使用

     

    C语言的指向函数指针用法

    #import <Foundation/Foundation.h>
    
    int sum(int value1,int value2)
    {
        return value1 + value2;
    }
    int minus(int value1,int value2)
    {
        return value1 - value2;
    }
    int main(int argc,onst char * argv[])
    {
        int (*sumP)(int,int);
        sumP = sum;
        NSLog(@"sum = %i",sumP(20,10));
        
        int (*minusP)(int,int)
        minusP = minus;
        NSLog(@"minus = %i",minusP(20,10));
        
        return 0;
    }
    

    由于相同的部分可以抽离出来,所以需要使用typedef

    #import <Foundation/Foundation.h>
    
    int sum(int value1,int value2)
    {
        return value1 + value2;
    }
    int minus(int value1,int value2)
    {
        return value1 - value2;
    }
    
    typedef int (*calculte)(int,int)
    
    int main(int argc,onst char * argv[])
    {
        calculte sumP = sum;
        NSLog(@"sum = %i",sumP(20,10));
        
        calculte minusP = minus;
        NSLog(@"minus = %i",minusP(20,10));
        
        return 0;
    }

    OC的block的用法

    #import <Foundation/Foundation.h>
    
    int main(int argc,onst char * argv[])
    {
        int (^sumBlock)(int,int);
        sumBlock = ^(int value1,int value2){
            return value1 + value2;
        };
        NSLog(@"sum = %i",sumBlock(20,10));
        
        int (^minBlock)(int,int);
        minBlock = ^(int value1,int value2){
            return value1 - value2;
        };
        NSLog(@"min = %i",minBlock(20,10));
        
        return 0;
    }

    使用typedef之后:

    #import <Foundation/Foundation.h>
    
    typedef int (^calculteBlock)(int,int);
    
    int main(int argc,onst char * argv[])
    {
        calculteBlock sumBlock = ^(int value1,int value2){
            return value1 + value2;
        };
        NSLog(@"sum = %i",sumBlock(20,10));
        
        calculteBlock minBlock = ^(int value1,int value2){
            return value1 - value2;
        };
        NSLog(@"min = %i",minBlock(20,10));
        
        return 0;
    }

    block的应用场景

     

    在学习UI之后就会体会到block的好处。

    这段代码要多练习,练习到不用看源码就能熟练敲出来。

    #import <Foundation/Foundation.h>
    
    void Hello(void (^func)())
    {
        NSLog(@"Hello Wrold~");
        func();
        NSLog(@"Hello HeYang~");
    }
    
    
    void sayHello()
    {
        Hello(^{
            NSLog(@"Hello World,Hello HeYang~");
        });
    }
    
    int main(int argc, const char * argv[]) {
        @autoreleasepool {
            sayHello();
        }
        return 0;
    }

    举个block应用实例场景:

    需求:
        找到需要读取并需要操作的文件
    步骤:
        读取文件
        操作文件
        关闭文件
    分析:
        其中读取文件和关闭文件都是一样的
        而操作文件,会根据需求而变化,或者根据文件类型而不一样
    总结:
        这里就需要使用block把操作文件的功能分离出来。

    将Objc的m文件编译成C++文件的终端命令:

    cc -rewrote-objc xx.m(OC的m文件)

    然后在当前目录下就会出现后缀cpp的C++文件。

    block是存储在堆中还是在栈中?
    默认情况下block存储在栈中,如果对block进行一个copy操作,block会转移到堆中
    如果block在栈中,block中访问了外界的对象,那么不会对对象进行retain操作
    但如果是block在堆中,block中访问了外界的对象,那么会对外界的对象进行一次retain

    在MRC模式下,我们分析一下是不是会出现内存泄露

    Person *p = [[Person alloc]init];
    NSLog(@"retainCount = %lu",[p retainCount]);
    void (^myBlock)() = ^{
        NSLog(@"a = %@",p);
        NSLog(@"block retainCount = %lu",[p retain]);
    }
    Block_copy(myBlock);
    
    myBlock();

    如果在block中访问了外界的对象,一定要给对象加上__block,只要加上了__block,哪怕block在堆中,也不会对外界的对象进行retain。

    加了__block就是地址传递,不加__block是值传递。正因为是值传递,所以可以访问其值,或者return返回其值。

  • 相关阅读:
    Java单例模式
    Java中子类覆盖父类方法所必须满足的条件
    Java中break、continue及标签等跳转语句的使用[下]
    CSS控制图片显示区域
    rabbitmq 用户管理
    rabbitmq web管理页面无法访问
    centos6.5 以 zero-dependency Erlang from RabbitMQ 搭建环境
    docker 解决:Get http:///var/run/docker.sock/v1.19/version: dial unix /var/run/docker.sock: no such file or directory. Are you trying to connect to a TLS-enabled daemon without TLS?
    解决:java.lang.ArrayIndexOutOfBoundsException: 160 at com.alibaba.fastjson.serializer.SerializeWriter.writeStringWithDoubleQuote(SerializeWriter.java:868)
    centos 解决:Another app is currently holding the yum lock; waiting for it to exit
  • 原文地址:https://www.cnblogs.com/goodboy-heyang/p/4934907.html
Copyright © 2011-2022 走看看