美文网首页将来跳槽用iOS Developer
iOS开发 Block的使用方法和规范,以及可能遇到的问题

iOS开发 Block的使用方法和规范,以及可能遇到的问题

作者: Dylan大魔王 | 来源:发表于2017-07-27 17:01 被阅读60次

    常用Block,写一个文章来避免自己犯错 ,之后会不断补充Block的使用方式

    1.什么是Block

    1. Block是一种多个文件之间的数据交互方式
      是Objective-C特有的一种数据类型
      它可以保存一段代码,在合适的时候取出来调用

    2. 常见格式

    //不带参数,不带名称
    ^{
    
    }
    
    //带名称
    void (^someBlock)() = ^{
    
    }
    
    //带参数带返回值
    int (^addBlock)(int a, int b) = ^(int a, int b){
        return a+b;
    }
    
    1. 两种定义方式
    @property (copy) void(^MyBlock)(void);
    
    typedef void(^MyBlock)(void);//常用的block建立
    @property (nonatomic, copy) MyBlock block;
    
    1. block在一些场合下需要用到copy,比如下边这段代码,如果在栈上if和else里会被释放
    void (^block)();
    if(xxx){
        block = ^{
            NSLog(@"1");
        }
    }else{
        block = ^{
            NSLog(@"2");
        }
    }
    block();
    
    

    这个时候我们需要用到copy把它放在堆上来,避免它被释放

    void (^block)();
    if(xxx){
        block = [^{
            NSLog(@"1");
        } copy];
    }else{
        block = [^{
            NSLog(@"2");
        } copy];
    }
    block();
    
    1. 在属性中声明block用什么来修饰?strong和copy都一样

    使用copy修饰block是MRC时期的遗留物,这在MRC时期是至关重要的事情,但是使用ARC的现在,strong是可以代替的,只是一个习惯问题而已。

    block其实是一个对象,有和其他对象相同的一些特性和信息,看起来像是C语言里的函数

    2.Block优缺点

    相比代理,Block更轻便简单,不需要定义代理,协议,可以直接使用
    如果有很多相关方法,我们就需要使用代理,这样更方便管理
    使用Block需要避免循环引用

    3.Block循环引用

    1. Block循环引用种类大概有三种,就不列举了,我们只需要知道如何避免循环引用就可以了

    2. 防止Self循环引用,当然括号里可以使任何对象,个人建议凡是Block中的对象都要使用 __weak

    __weak typeof(self) weakSelf=self;
    __weak TSController * weakCtl=Ctl;
    
    1. 在 block 中进行强引用防止被释放,一半多次使用的时候需要加strong,防止block没有跑完self被释放
        typeof(self) __strong strongSelf = weakSelf;
        ViewController *bSelf = wSelf;
    

    4.Block中修改局部变量需要使用__block 修饰

    1. Block中修改局部变量需要使用__block
      Block修饰符在ARC中Copy和Strong一样的,在MRC中用Copy
      Block中有时候需要用到Strong

    2. 保证代码在执行到block中,self不会被释放,当block执行完后,会自动释放该strongSelf

    分享一个大神的总结

    5.Block常见用法(会不断补充)

    1. 在头文件中定义Block属性,进行值传递

      一般在View向Controller进行值传递的时候经常用到

    定义

    @property (strong,nonatomic)void (^TSHTToolCollectionCellBlock)(TSHTToolCollectionCell * cell);
    

    实现

        __weak typeof(self) weakSelf = self;
        [cell setTSHTToolCollectionCellBlock:^(TSHTToolCollectionCell * htcell) 
        {
            NSString * msgString=[NSString stringWithFormat:@"%ld/9\n长按图片可以拖动排序",(weakSelf.imageSelectArray.count)];
            weakSelf.msgLabel.text=msgString;
        }];
    

    调用

        if (self.TSHTToolCollectionCellBlock)
        {
            self.TSHTToolCollectionCellBlock(self);
        }
    
    1. 定义带Block的方法

      涉及到线程的方法,我们需要回到主线程

    - (void)clipImageComplete:(void (^)(UIImage * clipedImage))complete
    {
        __weak typeof(self) weakSelf = self;
        dispatch_queue_t conQueue = dispatch_queue_create("concurrentQueue", DISPATCH_QUEUE_CONCURRENT);
        dispatch_async(conQueue, ^
                       {
                           //开始画图
                           UIImage * clipedImage=[weakSelf clipImage];
                           dispatch_sync(dispatch_get_main_queue(), ^{
                               complete(clipedImage);
                           });
                       });
    }
    

    注意:分享一个宏定义

    #ifndef weakify
        #if DEBUG
            #if __has_feature(objc_arc)
            #define weakify(object) autoreleasepool{} __weak __typeof__(object) weak##_##object = object;
            #else
            #define weakify(object) autoreleasepool{} __block __typeof__(object) block##_##object = object;
            #endif
        #else
            #if __has_feature(objc_arc)
            #define weakify(object) try{} @finally{} {} __weak __typeof__(object) weak##_##object = object;
            #else
            #define weakify(object) try{} @finally{} {} __block __typeof__(object) block##_##object = object;
            #endif
        #endif
    #endif
    
    #ifndef strongify
        #if DEBUG
            #if __has_feature(objc_arc)
            #define strongify(object) autoreleasepool{} __typeof__(object) object = weak##_##object;
            #else
            #define strongify(object) autoreleasepool{} __typeof__(object) object = block##_##object;
            #endif
        #else
            #if __has_feature(objc_arc)
            #define strongify(object) try{} @finally{} __typeof__(object) object = weak##_##object;
            #else
            #define strongify(object) try{} @finally{} __typeof__(object) object = block##_##object;
            #endif
        #endif
    #endif
    

    使用时候直接在block外边@weakify(self),在block里边使用@strongify(self)

    相关文章

      网友评论

        本文标题:iOS开发 Block的使用方法和规范,以及可能遇到的问题

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