美文网首页
《Objective-C高级编程》Blocks 阅读笔记 it

《Objective-C高级编程》Blocks 阅读笔记 it

作者: dibadalu | 来源:发表于2016-02-19 15:17 被阅读158次

    《Objective-C高级编程》Blocks 阅读笔记系列

    《Objective-C高级编程》Blocks 阅读笔记 item1(Blocks概要和模式)
    《Objective-C高级编程》Blocks 阅读笔记 item2(Block的实质)
    《Objective-C高级编程》Blocks 阅读笔记 item3(截获自动变量值)
    《Objective-C高级编程》Blocks 阅读笔记 item4(__block说明符)
    《Objective-C高级编程》Blocks 阅读笔记 item5(Block存储域)
    《Objective-C高级编程》Blocks 阅读笔记 item6(__block变量存储域)
    《Objective-C高级编程》Blocks 阅读笔记 item7(截获对象)
    《Objective-C高级编程》Blocks 阅读笔记 item8(__block变量和对象)
    《Objective-C高级编程》Blocks 阅读笔记 item9(Block循环引用)
    《Objective-C高级编程》Blocks 阅读笔记 item10(copy/release实例方法)

    2.3 Blocks的实现

    2.3.9 copy/release

    *** ARC无效时,需要用copy实例方法手动将Blocl从栈复制到堆,用release实例方法来释放复制的Block。 ***

    void (^blk_on_heap)(void) = [blk_on_stack copy];
    
    [blk_on_heap release];
    

    *** 只要Block有一次复制并配置在堆上,就可通过retain实例方法持有。***

    [blk_on_heap retain];
    

    *** 但是,对于配置在栈上的Block调用retain实例方法则不起任何作用。 ***

    [blk_on_stack retain];
    

    该源代码中,虽然对赋值给blk_on_stack的栈上的Block调用了retain实例方法,但实际上对此源代码不起任何作用。因此,推荐使用copy实例方法来持有Block(不用retain实例方法)。

    由于Block是C语言的扩展,所以在C语言中也可以使用Block语法。此时使用“Block_copy函数”“Block_release函数”代替copy/release实例方法。

    void (^blk_on_heap)(void) = Block_copy(blk_on_stack);
    
    Block_release(blk_on_heap);
    

    *** ARC无效时,__block说明符被用来避免Block中的循环引用。***
    这是由于当Block从栈复制到堆时,若Block使用的变量为附有__block说明符的id类型或对象类型的自动变量,不会被retain;若Block使用的变量为没有__block说明符的id类型或对象类型的自动变量,则被retain。

    typedeft void (^blk_t)(void);
    
    @interface MyObject : NSObject
    {
        blk_t blk_;
    }
    @end
    
    @implementation MyObject
    - (id)init
    {
        self = [super init];
        
        blk_ = ^{NSLog(@"self = %@", self);};
        
        return self;
    }
    
    - (void)dealloc
    {
        NSLog(@"dealloc");
    }
    @end
    
    int main()
    {
        id o = [[MyObject alloc] init];
        
        NSLog(@"%@", o);
        
        return 0;
    }
    
    

    该源代码无论ARC有效还是无效都会引起循环引用,Block持有self,self持有Block。

    可使用__block变量来避免出现该问题。

    - (id)init
    {
        self = [super init];
        
        __block id blockSelf = self; 
        
        blk_ = ^{NSLog(@"self = %@", blockSelf);};
        
        return self;
    }
    

    这时,由于Block使用__block变量,所以不会被retain。

    注意

    • ARC有效时,__block说明符和__unsafe_unretained修饰符一起使用,来解决附有__unsafe_unretained修饰符的自动变量不能retain的问题。
    • __block说明符在ARC有效无效时的用途有很大的区别,所以,在使用__block说明符必须清楚源代码是在ARC有效还是无效的情况下编译。

    相关文章

      网友评论

          本文标题: 《Objective-C高级编程》Blocks 阅读笔记 it

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