iOS-關鍵字-assign weak

一,解釋什麼時候用assgin什麼時候用weak

回答:ARC之後纔有weak,weak是弱指針,當使用weak關鍵字修飾成員變量的時候,成員變量內部是用__weak修飾的,不會讓引用計數器+1,如果指向對象被銷燬,指針會自動清空,就不會報壞內存訪問了

當使用assgin修飾的時候,內部是用__unsafe_unretained修飾的,不會讓引用計數器+1,如果指向對象被銷燬,指針不會清空   如果這時候訪問對象的指針,就會有壞內存訪問錯誤


如下圖:



示例代碼如下:

//  ViewController.m

#import "ViewController.h"

@interface ViewController ()

@property (nonatomic, assign 或//weak ) UIView *redView;

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
   
    UIView *view = [[UIView alloc] init];
    view.backgroundColor = [UIColor redColor];
    
//    [self.view addSubview:view];
//如果註釋掉上面的代碼,點擊屏幕的時候是不會有view出現的,因爲view是局部變量,{}之後就被銷燬了, 如果使用weak修飾運行不會報錯,因爲view被銷燬之後,指針也會自動清空,所以不會報壞內存訪問
如果是assign修飾,view被銷燬之後,指針不會清空, _redView.frame = CGRectMake(50, 50, 200, 200);指針訪問對象的時候就會報錯,因爲指針沒有被清空
    _redView = view;
}

- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
    _redView.frame = CGRectMake(50, 50, 200, 200);
    
}

@end

補充:weak內部實現原理:


Runtime維護了一個weak表,用於存儲指向某個對象的所有weak指針。weak表其實是一個hash(哈希)表,Key是所指對象的地址,Value是weak指針的地址(這個地址的值是所指對象的地址)數組。

1、初始化時:runtime會調用objc_initWeak函數,初始化一個新的weak指針指向對象的地址。

2、添加引用時:objc_initWeak函數會調用 objc_storeWeak() 函數, objc_storeWeak() 的作用是更新指針指向,創建對應的弱引用表。

3、釋放時,調用clearDeallocating函數。clearDeallocating函數首先根據對象地址獲取所有weak指針地址的數組,然後遍歷這個數組把其中的數據設爲nil,最後把這個entry從weak表中刪除,最後清理對象的記錄。


追問的問題一:


1.實現weak後,爲什麼對象釋放後會自動爲nil?

runtime 對註冊的類, 會進行佈局,對於 weak 對象會放入一個 hash 表中。 用 weak 指向的對象內存地址作爲 key,當此對象的引用計數爲 0 的時候會 dealloc,假如 weak 指向的對象內存地址是 a ,那麼就會以 a 爲鍵, 在這個 weak 表中搜索,找到所有以 a 爲鍵的 weak 對象,從而設置爲 nil 。


追問的問題二:


2.當weak引用指向的對象被釋放時,又是如何去處理weak指針的呢?

1、調用objc_release

2、因爲對象的引用計數爲0,所以執行dealloc

3、在dealloc中,調用了_objc_rootDealloc函數

4、在_objc_rootDealloc中,調用了object_dispose函數

5、調用objc_destructInstance

6、最後調用objc_clear_deallocating,詳細過程如下:

a. 從weak表中獲取廢棄對象的地址爲鍵值的記錄

b. 將包含在記錄中的所有附有 weak修飾符變量的地址,賦值爲   nil

c. 將weak表中該記錄刪除

d. 從引用計數表中刪除廢棄對象的地址爲鍵值的記錄



發佈了4 篇原創文章 · 獲贊 1 · 訪問量 9萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章