Block的三種類型

在沒有訪問局部變量的情況下,Block的本質類似于一個閉包,它具有參數(shù)和返回值,并可以像普通函數(shù)一樣存儲在全局區(qū),被稱為"全局Block"。
如果我們在一個函數(shù)內部創(chuàng)建了一個block,該block內部代碼引用了該函數(shù)內的某些局部變量(此時該block為棧block(stackBlock)),為了防止在block調用時引用的局部變量在原始作用域被銷毀,我們需要把block以及該局部變量copy到堆上(此時該block為堆block(mallocBlock)),以確保block可以被正常執(zhí)行。

auto變量 & static變量

// 在聲明變量時,如果沒有添加static關鍵字,那么默認為auto變量,在函數(shù)調用結束后自動銷毀
(auto) int a = 10;
// 靜態(tài)變量,儲存于全局區(qū),方法調用結束后不會銷毀
static int a = 10;

1.全局block

如果block中沒有訪問任何外部變量,則將被存儲在全局區(qū)中,不會被銷毀(這種不訪問外部變量的情況下我們一般會直接定義方法)

- (void)viewDidLoad {
    [super viewDidLoad];
    void (^block1)(void) = ^{};     
    NSLog(@"%@", [block1 class]); // __NSGlobalBlock__
}

2.MRC模式中的棧block

如果block中引用了auto變量, 那么block的將被存儲在棧中。在MRC模式下方法調用結束后block的內存會被回收。

- (void)viewDidLoad {
    [super viewDidLoad];
    int age = 10;
    void (^block1)(void) = ^(){
        NSLog(@"%d", age);
    };
    NSLog(@"%@", [block1 class]); // __NSStackBlock__
}
2.1 MRC模式中棧block導致的問題

由于stackBlock引用的block在getBlock方法執(zhí)行完成后就被銷毀了,所以當在viewDidLoad方法中調用stackBlock時,age的值發(fā)生了錯誤

#import "ViewController.h"

typedef void (^Myblock)(void);
Myblock stackBlock;

@interface ViewController ()

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    [self getBlock];
    // __NSStackBlock__
    NSLog(@"%@", [stackBlock class]);
    // -307953584
    stackBlock();
}

- (void)getBlock {
    int age = 100;
    stackBlock = ^(){
        NSLog(@"%d", age);
    };
}

@end
2.1 解決MRC模式中棧block導致的問題

getBlock方法中將棧block賦值給stackBlock時,我們對棧block進行一次copy操作,這樣就會將該棧block的副本存儲在堆中,該副本不會隨著方法執(zhí)行結束而銷毀。

- (void)viewDidLoad {
    [super viewDidLoad];
    [self getBlock];
    // __NSMallocBlock__
    NSLog(@"%@", [stackBlock class]);
    // -100
    stackBlock();
}

- (void)getBlock {
    int age = 100;
    stackBlock = [^(){
        NSLog(@"%d", age);
    } copy];
}

3 堆block

在MRC模式下,堆Block是由棧Block拷貝而來,需要程序員手動調用copy方法來實現(xiàn)。
而在ARC模式下,為了安全起見,xcode會對棧block的賦值行為自動進行一次copy操作(即使賦值給以Strong修飾的成員變量,依然會進行一次copy操作,在堆中創(chuàng)建一個新副本)

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

相關閱讀更多精彩內容

友情鏈接更多精彩內容