block詳解

一、簡述:

a.每一個方法都是在被調用的時候從硬盤到內存,然後去執行,執行完就消失。在內存的棧區,不需要我們去管理。
b.block,我們成爲代碼塊,它類似一個方法,也是在棧區的。
c.如果我們使用block作爲一個對象的屬性,則用copy關鍵詞修飾。這樣系統會把block的實現拷貝一份到堆區,保證代碼塊不會提前消亡,使我們對應的屬性擁有該block的所有權。
d.block常用於對象之間的通信(反向傳值和方法傳遞)。

二、使用:


#import "ViewController.h"

typedef void (^MyBlock) (void);//初始化

@interface ViewController ()

@property (nonatomic,copy)MyBlock block;//定義一個block屬性


@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.
    
    //實現一個block 這個block實現代碼是在棧區的,也就是說,當viewDidLoad這個方法執行完之後,block就消失了。
    void(^block)(void) = ^{
        NSLog(@"block的使用");
    };
    //賦值給屬性_block 此時就完成了copy _block指針指向堆中一塊內存(存放的是block的實現代碼),_block就一直擁有了代碼塊的使用權,直到 viewcontroller
    _block = block;
    //一般我們不會這樣寫,block的實現都是在另一個類的對象中實現。
    
}

三、使用block傳值時需要注意的幾點:

1.我們在實現block的時候,一般都會使用到外部(block大括號之外)變量。我們知道,局部變量(非靜態)是不能在外部使用的,而block又類似是一個方法,那他爲什麼可以使用外部變量呢。

- (void)viewDidLoad {
    [super viewDidLoad];
    
    int a = 10;//a對於_block來說就是一個外部變量
    
    _block = ^{
        NSLog(@"a = %d",a);//但是,此時是可以使用a的。
    };
    
}

其實,這是因爲OC是一種運行時語言,我們寫的OC代碼最終都是要轉換成C語言的代碼去執行的。我們通過運行時代碼可以知道,系統會把使用到的外部變量通過參數列表傳遞給block,也就變成了block內部的局部變量,所以可以使用。

2.而在傳遞的時候,對於基本數據類型的外部變量來說,系統默認傳遞的僅僅是值,也就是說這個局部變量是不能修改的。如果想修改值,會使用__block來修飾這個變量。這樣一來,系統在傳遞的時候,傳的就是外部變量的地址,這樣我們就可以修改值了。

__block int a = 10;//用__block修飾之後,系統會傳遞a的地址(&a)
    
    _block = ^{
        
        a += 20;
        NSLog(@"a = %d",a);//有地址,當然就可以修改a的值了。此時a的值是30
    };

3.對於對象類型,傳遞的是地址,同時默認對該對象進行了一次強引用。系統進行了強引用,而他又對該對象的內存管理袖手旁觀,也就是說,他只做了強引用,但是沒有做釋放操作。這個時候就會造成內存泄漏。所以,我們在使用對象的時候,在MRC下,都會使用__block修飾,在ARC下,使用__weak修飾,這樣一來,系統在傳遞的時候就不會對該對象進行強引用,避免了內存泄漏。

- (void)viewDidLoad {
    [super viewDidLoad];
    
    UIView *view = [[UIView alloc] init];
    
    __weak typeof(view)_view = view;//_view和view指向同一塊內存,而_view是弱引用,view的retainCount還是1.
    
    _block = ^{
        //view.frame = CGRectMake(0, 0, 100, 100);//在block內部使用view對象,系統會對view強引用,此時會造成內存泄漏。
        _view.frame = CGRectMake(0, 0, 100, 100);
    };
    
}

參考資料:https://www.cnblogs.com/libaoshen/p/5861466.html

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章