iOS底層原理(9)-block-copy屬性,auto變量

對(duì)象類型的auto變量

  • 1.當(dāng)block內(nèi)部訪問了對(duì)象類型的auto變量時(shí)

    • 如果block是在棧上,將不會(huì)對(duì)auto變量產(chǎn)生強(qiáng)引用
  • 2.如果block被拷貝到堆上

    • 會(huì)調(diào)用block內(nèi)部的copy函數(shù)
    • copy函數(shù)內(nèi)部會(huì)調(diào)用_Block_object_assign函數(shù)
    • _Block_object_assign函數(shù)會(huì)根據(jù)auto變量的修飾符(__strong、__weak、__unsafe_unretained)做出相應(yīng)的操作,形成強(qiáng)引用(retain)或者弱引用
  • 3.如果block從堆上移除

    • 會(huì)調(diào)用block內(nèi)部的dispose函數(shù)
    • dispose函數(shù)內(nèi)部會(huì)調(diào)用_Block_object_dispose函數(shù)
    • _Block_object_dispose函數(shù)會(huì)自動(dòng)釋放引用的auto變量(release)
image.png

代碼一 - 運(yùn)行在ARC環(huán)境下 - block被強(qiáng)指針引用,所以在堆上。

#import <Foundation/Foundation.h>
#import "Person.h"

typedef void (^MJBlock)(void);

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        
        MJBlock block;
        {
            Person *person1 = [[Person alloc] init];
            person1.age = 10;
            person1.name = @"person1";
            
            Person *person2 = [[Person alloc] init];
            person2.age = 100;
            person2.name = @"person2";
            
            Person *person3 = [[Person alloc] init];
            person3.age = 1000;
            person3.name = @"person3";

            __weak Person *weakPerson = person2;
            __strong Person *strongPerson = person3;
            
            block = ^{  // 因?yàn)樵揵lock已經(jīng)被強(qiáng)引用,所以此時(shí)在堆上
                NSLog(@"---------%d", person1.age);
                NSLog(@"---------%d", weakPerson.age);
                NSLog(@"---------%d", strongPerson.age);
            };
            
            NSLog(@"end");
        }
        NSLog(@"------");
    }
    return 0;
}

在不同的地方打斷點(diǎn)調(diào)試運(yùn)行

  • 1.在第一個(gè)括號(hào)內(nèi)打斷點(diǎn)
image.png

因?yàn)槿齻€(gè)person對(duì)象都還在作用域內(nèi),所以大家都還沒有被釋放

    1. 在第二個(gè)括號(hào)內(nèi)打斷點(diǎn)
image.png

因?yàn)檫@個(gè)時(shí)候已經(jīng)超出三個(gè)person變量的作用域,因?yàn)閣eakPerson被weak修飾,所以這個(gè)時(shí)候被釋放。

    1. 在第三方括號(hào)內(nèi)打斷點(diǎn)
image.png

因?yàn)檫@個(gè)時(shí)候已經(jīng)超出block的作用域,block被釋放,所以被它所引用的的對(duì)象也釋放了

代碼一 - 運(yùn)行在ARC環(huán)境下 - block沒有強(qiáng)指針引用,所以在棧上。

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        
        MJBlock block;
        {
            Person *person1 = [[Person alloc] init];
            person1.age = 10;
            person1.name = @"person1";
            
            Person *person2 = [[Person alloc] init];
            person2.age = 100;
            person2.name = @"person2";
            
            Person *person3 = [[Person alloc] init];
            person3.age = 1000;
            person3.name = @"person3";

            __weak Person *weakPerson = person2;
            __strong Person *strongPerson = person3;
            
            ^{  // 因?yàn)樵揵lock沒有被強(qiáng)引用,所以此時(shí)在棧上
                NSLog(@"---------%d", person1.age);
                NSLog(@"---------%d", weakPerson.age);
                NSLog(@"---------%d", strongPerson.age);
            };
            
            NSLog(@"end");
        }
        NSLog(@"------");
    }
    return 0;
}

運(yùn)行結(jié)果如下

  • 1.在第一個(gè)括號(hào)內(nèi)打斷點(diǎn)
image.png

因?yàn)槿齻€(gè)person對(duì)象都還在作用域內(nèi),所以大家都還沒有被釋放

  • 2.在第二個(gè)括號(hào)內(nèi)打斷點(diǎn)


    image.png

因?yàn)閎lock沒有被強(qiáng)指針引用,在棧上,并且已經(jīng)超出block的作用域,所以block被釋放,被它所引用的對(duì)象也釋放了。

面試代碼一

- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
    Person *p = [[Person alloc] init];
    __weak Person *weakP = p;
    
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
        NSLog(@"1-------%@", p);
        
        dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
            NSLog(@"2-------%@", weakP);
        });
    });
    
    NSLog(@"touchesBegan:withEvent:");
}

運(yùn)行結(jié)果

image.png

1秒后Person被釋放

面試題二

- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
    Person *p = [[Person alloc] init];
    __weak Person *weakP = p;
    
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
        NSLog(@"1-------%@", weakP);
        
        dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
            NSLog(@"2-------%@", p);
        });
    });
    
    NSLog(@"touchesBegan:withEvent:");
}

運(yùn)行結(jié)果


image.png

person 3秒后才被釋放


本文參考借鑒MJ的教程視頻,非常感謝.


項(xiàng)目演示代碼
iOS-block-auto-variable
iOS-block-變量


更多block相關(guān)文章

iOS-block底層原理詳解-本質(zhì),類型,copy屬性

iOS-block底層原理詳解之__block屬性

iOS-block底層原理之循環(huán)引用詳解

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容