iOS中代理屬性為什么要用Weak修飾?

iOS中代理屬性為什么要用Weak修飾?

一.寫在前面

代理設計模式,在iOS開發過程中,是一個非常常見的設計模式,可以說用的范圍非常廣泛,而對初學者來講,常常對代理的屬性修飾用weak存在疑惑,因此下面就解釋一下其中非常簡單的道理.

二.必要的知識補充.

  • 眾所周知,OC是一門面向對象的語言,因此,對象這個詞,在iOS中是個非常重要的詞匯了(扯淡).開發中,創建一個對象是再常見不過的事兒了,每個對象的創建都需要在內存中分配一定的空間,簡單的說,因為內存是有限的,所以一些沒有必要存在的對象,我們需要及時的去將它釋放,還原更多的內存空間(如果不進行釋放就會造成"內存泄露").
  • 因此,在iOS中引入了引用計數(retainCount)這個詞匯,規定:只要引用計數為零,對象就會被釋放,注意是規定,規定就不要問為什么了.
  • 這里主要介紹strong和weak兩個修飾詞(不能偏離重點),如果想了解其他的修飾詞(retain,copy,getter,setter...),可以Google一下,簡單點來講strong屬性會使引用計數+1,而weak修飾的對象不會使引用計數改變.
  • OK了,有了上面的只是準備,應該可以理解下面的要解釋的東西了.

三.案例說明

  1. 案例介紹
```
    案例中的類介紹: 案例共用到三個類,Baby類(嬰兒類),LLBabyServant類(保姆類),ViewControllr類(控制器類),其中說明問題的關鍵是之前兩個類.
    假設,嬰兒類要想做一些事情(像換衣服了,方便了之類的...)就必須具有代理的屬性,因此指定了一個協議<LLBabyDelegate>,合情合理.而保姆需要成為嬰兒的代理,必須遵循協議,廢話不多說,上代碼!
```
  1. 首先介紹Baby類-----.h文件
```
// 制定協議
@protocol LLBabyDelegate <NSObject>
//這里可以編寫代理方法(該案例中用不到所以就不寫了)
@end

@interface Baby : NSObject
/**
 *  baby的代理屬性(這里用的是weak修飾,正確的做法)
 */
@property(nonatomic, weak) id<LLBabyDelegate>delegate;
@end

```

說明:跟上面描述的一樣嬰兒擁有一個代理的屬性.并且用修飾詞Weak修飾的.

接著粘Baby類-----.m文件

```
@implementation Baby
- (void)dealloc
{
    NSLog(@"Baby被銷毀了");
}
@end
```
說明:該方法的作用是當該類的對象被銷毀時會調用-dealloc方法(在這個案例中用來觀察對象是否被銷毀了)
  1. 再有介紹BabyServant類-----.m文件

    //BabyServant類也就是保姆必須遵循代理協議 
    @interface BabyServant()<LLBabyDelegate>
    //并有一個需要照顧的Baby
    @property(nonatomic, strong) Baby *baby;
    
    @end
    
    @implementation LLBabyServant
    //初始化方法
    - (instancetype)init
    {
     self = [super init];
    
        if (self) {
        // 初始化'嬰兒'對象
        self.baby = [[Baby alloc]init];
        // 設置'自己(LLBabyServant)'為(Baby)類的代理
        self.baby.delegate = self;
        }
    
     return self;
    }
    
  2. 我們介紹最后一個類 ViewController類

    @implementation ViewController
    
    - (void)viewDidLoad {
        [super viewDidLoad];
    
        LLBabyServant *servant = [[LLBabyServant alloc]init];
    
        }
    
    @end
    
    

    說明: 在ViewController的方法ViewDidLoad中創建保姆對象,并且該對象作用的范圍是這個方法內部.這個方法執行完成,servant對象就會被銷毀了.

    上面的代碼執行完成之后,運行結果如下:

    2016-02-18 15:06:41.151 代理weak案例[1805:173874] LLBabyServant 被銷毀了
    2016-02-18 15:06:41.152 代理weak案例[1805:173874] Baby類被銷毀了
    
    
這就說明LLBabyServant對象和Baby對象在沒有用處之后都會被銷毀,但是如果用代理用strong修飾,而不是用weak修飾,則不會打印上面的結果!

四.分析

1. 用weak分析圖如下:
  • 整體來看如下圖

  • 分開來看如下圖:

    如果weak的話,在程序運行的時候不會造成循環引用,對象都會被順利的銷毀,所以會調用嬰兒類和保姆類的delloc方法

2. 用strong分析如下
  • 整體來看如下圖

  • 分開來看如下圖


    如果strong的話,在程序運行的時候會造成循環引用(意思就是reatainCount不為0,只要有實線引用,計數器就+1),對象都不會的銷毀,所以會調用嬰兒類和保姆類不會調用delloc方法,從而造成了內存泄露的問題


這就是為什么代理屬性要用weak修飾的原因了!如果有哪里不嚴謹或者錯誤的地方,希望能夠多多交流.

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容