block语法

作者: Cy_Star | 来源:发表于2017-11-22 16:20 被阅读36次

    一、block应用范围

    1、动画的转场
    2、网络的事件处理
    3、两个对象或者多个对象之间的通讯
    4、多线程的处理
    (从iOS4.0开始就应用得非常广泛)

    二、Block

    block和C语言中的函数(函数指针)有些类似,但需要编译器和运行时的堆或栈的支持,主要用在回调函数的地方,当两个对象进行通讯需要回调的时候广泛应用block,在一些小的操作当中可以很好代替代理来作为回调操作的支撑。

    三、Block和C语言函数指针的区别

     /*
      C 函数指针 typedef 定义
      typedef  int (*  SumBlockT)(int a);
    */ 
    int (*  AFunc) (int   a) //C 函数指针 
    
    
    /*
      Block   typedef 定义
      typedef  int (^  SumBlockT)(int a, int b);
    */ 
     int (^  BFunc) (int a, int b)  // Blocks
    

    四、调用Block

        void (^ myblock_1)(void); //申明block,变量是myblocks_1
        void (^ myblock_2)(void) = NULL; //申明block,myblocks_2赋值为空
        myblock_2 = ^(void)
        {
            NSLog(@"只是赋值,可以说是这block函数块赋值给myblocks_2");
        };
        myblock_2(); //执行myblock_2  ,运行结果如下。
    
    block—1.png
      int (^ myblock_3)(int a,int b) =^(int a, int b)
        {
            int c = a+b;
        
            return c;
        };
        int a = myblock_3(10,20);
        NSLog(@"%d",a);
    
    block_2.png
    _ _block int sum = 0;
    int (^myblock4)(int a, int b) =^(int a ,int b){
        
        sum = a+b;
        return sum;
    };
    myblock4(20,30);
    NSLog(@"%d",sum);
    
    block_3.png
    // 定义block 的 typedef
    typedef int (^SumBlock)(int a, int b);
    SumBlock myblock5 = ^ (int a,int b){
        NSLog(@"%d",a+b);
        return 0;
    };
    myblock5(50,10);
    

    五、两个代理之间通过Block通讯

    Dog 跟 Person 之间的通讯

    Dog.h文件
    #import <Foundation/Foundation.h>
    
    @interface Dog : NSObject
    {
        int _ID;
        int _barkCount;
        NSTimer * timer;//定时器,定时发送信息
        //定义一个block变量
        void (^ BarkCallback)(Dog * thisDog,int count);
    }
    @property (assign)int ID;
    
    //向外暴露一个函数 setBark: ,给 person 对象使用
    -(void) setBark:( void (^)(Dog * thisDog,int count))eachBrak;
    
    @end
    
    #pragma mark  ----------Dog.m 文件-------------------------------------------
    #import "Dog.h"
    @implementation Dog
    @synthesize ID = _ID;
    
    -(id)init
    {
      self = [super init];
    
      if (self) {
          timer = [NSTimer scheduledTimerWithTimeInterval:1.0f target:self selector:@selector(updateTimer:) userInfo:nil repeats:YES];
      }
      return self;
    }
    
    -(void)updateTimer:(id)arg
    {
        _barkCount++;
        NSLog(@"dog_ID %d barkCount %d",_ID ,_barkCount);
    
          //给 person 汇报一下
        // 调用 person 里面的 block
        if (BarkCallback) {
            BarkCallback(self,_barkCount);//调用从person传过来的block
        }
    }
    
    -(void) setBark:( void (^)(Dog * thisDog,int count) )eachBrak
    {
        BarkCallback = nil;
        BarkCallback = [eachBrak copy];
    }
    
    -(void)dealloc
    {
        BarkCallback = nil;
    }
    @end
    
    #pragma mark  ----------Person.h 文件-------------------------------------------
    #import <Foundation/Foundation.h>
    #import "Dog.h"
    
    @interface Person : NSObject
    {
        Dog *_dog;
    }
    @property(retain) Dog *dog;
    
    @end
    
    
    #pragma mark  ----------Person.m 文件-------------------------------------------
    #import "Person.h"
    @implementation Person
    
    @synthesize dog = _dog;
    
    -(void) setDog:(Dog *)dog
    {
        if (_dog != dog){
            _dog = nil;
            _dog = dog;
        
            [_dog setBark:^(Dog *thisDog, int count) {
                NSLog(@"person dog^ID %d count %d",[thisDog ID],count);
            }];
        }
    }
    
    -(Dog *) dog
    {
        return _dog;
    }
    
    -(void)dealloc
    {
        self.dog = nil;
    }
    
    @end
    
    
    #pragma mark  ----------main.m 文件 实现-------------------------------------------
    Person * xiaoLi = [[Person alloc] init];
    
    Dog *dog = [[Dog alloc]init];
    
    [dog setID:10];
    
    [xiaoLi setDog:dog];
    
    while (1) {
        [[NSRunLoop currentRunLoop]run];
    }
    

    输出结果如图下:

    图1.png

    六、_ _block关键字

    一个block内部可以引用自身作用外域的变量(static变量、extern变量、自由变量),定义变量时,不加存储修饰符,默认是自由变量(auto),auto变量保存在stack中,除了auto还存在register、static等存储修饰符;自由变量在 Block 中是只读的,在引入 block 的同时,还引入来一种特殊的 _ _block关键字变量存储修饰符。

    七、block 块回调产生的强引用

    上面的第五demo只是一部分,在实际开发过程中,比如很多网络请求的操作是要执行回调提供UI使用的,这个时候就会产生强引用内存泄漏的问题,双方互相持有,由于强引用的关系双方都没有其中一方去执行释放,这个时候就是双向强引用所产的问题。

    那么在很多OC 或者 Swift 的语法上也有很多用到了 block 回调,为什么没有产生强引用内存泄漏的问题呢,那是因为官方在语法内部做了操作,总的来说就是把双向强引用变成单向强引用,也就是有其中一方变成了弱引用先释放掉了,另一方自然也就释放掉了。

    下面举个例子,把双向强引用变成单向强引用,也是最常的block回调操作之一

    @implementation ViewController
    -(void)working
    {
        //执行网络数据请求并回调
        NetWork  * net_joke = [[NetWork alloc]init];
        __weak typeof(net_joke) net = net_joke;  /// 强引用变成弱引用
        // net_joke 的变成弱引用 net 在执行完block回调操作后,net_joke就会释放
    
        NSMutableArray * model_Array = [NSMutableArray array];
    
        [net setBark:^(NSDictionary *dic) {
        
            NSArray * result = dic[@"result"];
           // int count = 0;
        
            if (result) {
                for (NSDictionary * jokeDic in result) {
                
                    Joke_Model * joke = [[Joke_Model alloc]init];
                    [joke setTitle:jokeDic[@"title"]];
                    [joke setContent:jokeDic[@"content"]];
                    [model_Array addObject:joke];
                
                    Joke_Model * j = [[Joke_Model alloc]init];
                    j = model_Array[count];
                   // count++;
                
                    NSLog(@"%@,\n%@",j.title,j.content);
                    joke = nil;
                    j = nil;
                 }
            }
        }];
    }
    

    相关文章

      网友评论

        本文标题:block语法

        本文链接:https://www.haomeiwen.com/subject/aakgpxtx.html