iOS中使用block块的用法

本文来源地址:http://www.osjoin.com   

block块语法和c中的函数指针类似。

   函数的定义是一样的,但是,函数名就换成了(*p)

   回顾一下 c的函数指针用法

   

    //函数的指针精髓在?回调
    //int(*ps)(int,int) = sum;
    //NSLog(@"%d",ps(3,6));
  在此处创建了一个函数指针


   1:block的创建

   
//   int (^blo)(int a,int b) = ^(int a,int b)
//    {
//        return a+ b;
//    };


      在等号右边的 ^ 后面可以数据类型,即返回类型,但是在oc中这块系统会识别返回的数据类型。当然如果不返回数据,就不考虑返回值了。


   2:调用

   上面的block调用的时候,和函数指针调用类似。

   

int nums = blo(1,2);
    
NSLog(@"%d",nums);
调用完之后,打印一下数据。即可得到对应的数据。

  



   在来一个列子看看:利用块语法实现把“123”转换成123。

//    int   (^bloc)(NSString *nums) = ^(NSString *nums)
//    {
//        return  [nums intValue];
//    };



   3列子

   

     //1.编程实现:

实现一个block完成一个功能,第一个参数是一个数组,第二个参数是一个int类型变量,遍历数据,查看数据中是否存在这个数,如果存在返回下标,如果不存在返回-1。

    下面是实现和调用

  

int (^funcArry)(int a[5],int b) = ^(int a[5],int b)
    {
        int falg = -1;
        
        for (int index = 0; index < 5; index++) {
            if (a[index] == b) {
                return falg = index;
                break;
            }else
            {
                continue;
            }
        }
        
        return falg;
    };
    
    int ac[] = {1,2,3,4,5,6};
    int str = funcArry(ac,9);

  4:block使用局部变量和全局变量

     

  //定义一个局部变量
    __block int count = 0;
    //在block块里对局部变量访问,并且修改值,返回修改之后的值
    int (^blo)(int a) = ^(int a)
    {
        count = count + a;
       
        return count;
    };
  注意:在使用局部变量时,系统会提示一个错误。

   -------解决办法就是在使用的局部变量时,在局部的变量前加 __block,在block前加两个下划线。

  

    在使用全局变量时和普通变量一样的使用,好像没什么特别之处。



  5:实际应用场景

    1:有一个student类,属性全部为@public

    //code。。。

    处理之后会得到一个可变的数组。(也可以不是可变的数组)

NSMutableArray *arrys = [[NSMutableArray alloc] initWithObjects:stu,stu1,stu2,stu3,stu4, nil];
     [arrys sortUsingComparator:^NSComparisonResult(id obj1, id obj2) {
        //将上面的obj强制转换为studnent
        Student *curr = (Student *)obj1;
        Student *next = (Student *)obj2;
        
        //按年龄比较
        if (curr->_age < next->_age) {
            //返回值表示的是,要不要进行元素的交换
            return  YES;
        }
        else
        {
            return  NO;
        }
    }];

   在这里就用到了实际块语法,具体的解释没一行都有解释。

   当然在不可变的数组中用到的排序方法为:

   NSArray *resu = [arry sortedArrayUsingComparator:^NSComparisonResult(id obj1,id obj2) {};

  

6:在排序完之后打印的方法

   因为每个数据类型都是student的,所以在便利的时候用 student *stu

    for (Student *stuin arrys) {

        NSLog(@"%@++++++++++%ld",stu->_name,stu->_age);

    }

  事咧代码下载地址:http://download.csdn.net/detail/whuizhou/8862861



Block确实是个好东西, 但是用起来一定要注意循环引用的问题, 否则一不小心你就会发现, Oh My God, 我的dealloc肿木不走了...

__weak typeof(self) weakSelf = self;
dispatch_block_t block =  ^{
    [weakSelf doSomething]; // weakSelf != nil
    // preemption, weakSelf turned nil
    [weakSelf doSomethingElse]; // weakSelf == nil
};

如此在上面定义一个weakSelf, 然后在block体里面使用该weakSelf就可以避免循环引用的问题. 那么问题来了...是不是这样就完全木有问题了? 很不幸, 答案是NO, 还是有问题。问题是block体里面的self是weak的, 所以就有可能在某一个时段self已经被释放了, 这时block体里面再使用self那就是nil, 然后...然后就悲剧了...那么肿么办呢?


__weak typeof(self) weakSelf = self;
myObj.myBlock =  ^{
    __strong typeof(self) strongSelf = weakSelf;
    if (strongSelf) {
      [strongSelf doSomething]; // strongSelf != nil
      // preemption, strongSelf still not nil
      [strongSelf doSomethingElse]; // strongSelf != nil
    }
    else {
        // Probably nothing...
        return;
         
    }
};

解决方法很简单, 就是在block体内define一个strong的self, 然后执行的时候判断下self是否还在, 如果在就继续执行下面的操作, 否则return或抛出异常.

什么情况下会出现block里面self循环引用的问题? 这个问题问的好, 哈哈...简单来说就是双边引用, 如果block是self类的property (此时self已经retain了block), 然后在block内又引用了self, 这个情况下就肯定会循环引用了...

P.S. RAC里面有定义好的@weakify(self)和@strongify(self), 用起来灰常灰常的方便, 劝君尝试一下^_^


  • 如有问题可添加QQ群:234812704(洲洲哥之说)
  • 登录www.osjoin.com 第一时间查看最新文章
  • 欢迎各位一块学习,提高逼格!
  • 也可以添加洲洲哥的微信公众号

    更多消息

    更多信iOS开发信息 请以关注洲洲哥 的微信公众号,不定期有干货推送:

    这里写图片描述








你可能感兴趣的:(侵掠如火,Object-C)