一文看懂@dynamic 與 @synthesize 關鍵詞

@dynamic與@synthesize的最基本的理解

1、@property有兩個對應的詞,一個是@synthesize,一個是@dynamic。如果@synthesize和@dynamic都沒寫,那麼默認的就是@syntheszie var = _var;
2、@synthesize的語義是如果你沒有手動實現setter方法和getter方法,那麼編譯器會自動爲你加上這兩個方法。
3、@dynamic告訴編譯器,屬性的setter與getter方法由用戶自己實現,不自動生成。(當然對於readonly的屬性只需提供getter即可)。假如一個屬性被聲明爲@dynamic var,然後你沒有提供@setter方法和@getter方法,編譯的時候沒問題,但是當程序運行到instance.var =someVar,由於缺setter方法會導致程序崩潰;或者當運行到 someVar = var時,由於缺getter方法同樣會導致崩潰。編譯時沒問題,運行時才執行相應的方法,這就是所謂的動態綁定。

@dynamic 使用後而且沒有自己實現

-[Car name]: unrecognized selector sent to instance 0x6000000109e0

@dynamic 就是要來告訴編譯器,代碼中用@dynamic修飾的屬性,其getter和setter方法會在程序運行的時候或者用其他方式動態綁定,以便讓編譯器通過編譯。其主要的作用就是用在NSManageObject對象的屬性聲明上,由於此類對象的屬性一般是從Core Data的屬性中生成的,Core Data框架會在程序運行的時候爲此類屬性生成getter和Setter方法。

提前總結

1.@synthesize 該關鍵字沒什麼好說的,無非就是自動生成,而且現在都不用手動加,默認就是自動生成的
2.@dynamic 該關鍵字就是告訴編譯器,該屬性不需要系統幫忙自動生成,關鍵來了,當你一個繼承NSObject的對象,弄了一個屬性,顯然父類是沒有一樣的屬性的,這種情形下,你需要手動生成getter和setter,如果沒有生成,編譯階段沒問題,而你訪問的時候就會找不到方法而崩潰。
還有一種情形就是父類有個屬性,已經默認自動生成了,而子類也聲明瞭同樣的屬性,你如果也默認,不做其他操作,這種情形下,子類的屬性就會出現警告,由於屬性是繼承來的,默認是在父類實現getter和setter,子類警告不會在子類出現getter和setter,會去其父類查找,那麼你子類聲明dynamic,也就是告訴他我會手動生成或者我父類有,你別警告我了,你運行起來就能找到了,自然,警告消除,運行起來調用就會去調用父類的getter和setter,能找到,就不會崩潰


## 詳細介紹 關鍵詞的場景,之前@dynamic只在NSManagedObject的子類中遇到過,因爲NSManagedObject的子類是由CoreData直接生成的,其中對應參數(@property)的setter和getter方法也是由CoreData直接生成,並且不展現給你
## getter && setter 首先介紹一下什麼是setter和getter方法:

由名字也大致能猜出
getter方法是當你的程序某處讀取一個參數A的時候,會調用的方法,它會返回當前A的值

setter方法是當你的程序某處給參數A賦值的時候,會調用的方法,把新值賦值給變量A

接下來,我們看一個非常老的標準的setter && getter方法

@interface Sample()

@property(nonatomic, strong, readwrite)NSObject *sampleObject;
@end
@implementation Sample
@synthesize sampleObject = _sampleObject;

//getter
- (NSObject *)sampleObject
{
    return _sampleObject;
}

//setter
- (void)setSampleObject:(NSObject *)sampleObject
{
    _sampleObject = sampleObject;
}
@end

synthesize中文意思爲‘合成’,在編譯的過程中,編譯器會幫你自動生成getter和setter方法,也就是說,上述代碼中,把

- (NSObject *)sampleObject
- (void)setSampleObject:(NSObject *)sampleObject

兩個函數的實現刪除掉也是沒有關係的。因爲@synthesize語法糖會讓編譯器幫助你生成getter和setter方法
以上都是老的寫法,但是現在看來基本上都是自動默認的,即使你不寫@synthesize,它同樣會自動幫你生成getter和setter方法


@dynamic

於是就到了今天主要要講的@dynamic關鍵詞。之前也說到了,這個關鍵詞用的不多,最常見的地方還是在CoreData的NSManagedObject中會看見。


@dynamicA相當於告訴編譯器:“參數A的getter和setter方法並不在此處,而在其他地方實現了或者生成了,當你程序運行的時候你就知道了,所以別警告我了,如下警告示例”這樣程序在運行的時候,對應參數的getter和setter方法就會在其他地方去尋找,比如父類

Auto property synthesis will not synthesize property ‘viewModel’; it will be implemented by its superclass, use @dynamic to acknowledge intention


父類 ```oc @interface father() @property (nonatomic, strong, readwrite) NSObject *sampleObject; ... @synthesize sampleObject = _sampleObject; @end ```

子類

@interface child : father
@property (nonatomic, strong, readwrite) NSObject *sampleObject;
...
@dynamic sampleObject;
@end

這樣的話,如果你在子類中調用sampleObject,則會調用父類的getter方法。

原理場景1

比如類遵守一個delegate時,delegate中的參數在父類的初始化方法中就賦值了,而子類的沒有自己的初始化方法的時候,子類中的此參數就可以設爲@dynamic,即和父類共用一個參數

MVVM實戰場景2

基類控制器.h和.m部分代碼

@interface MKJBaseViewController : UIViewController
@property (nonatomic, strong, readonly) MKJBaseViewModel  *viewModel;
@end


@interface MKJBaseViewController ()
@property (nonatomic, strong) MKJBaseViewModel  *viewModel;
@end
@implementation MKJBaseViewController
- (instancetype)initWithViewModel:(MKJBaseViewModel *)viewModel{
    self = [super initWithNibName:nil bundle:nil];
    if (self) {
        _viewModel = viewModel;
    }
    return self;
}

子類.h,.m文件部分代碼 ```oc @interface MKJMainViewController : MKJBaseViewController @property (nonatomic,strong,readonly) MKJMainViewModel *viewModel; @end

@interface MKJMainViewController ()

@end

@implementation MKJMainViewController
@dynamic viewModel;


<font size = 4 color = red>上面部分代碼可以看出,子類已經有一個ViewModel用來初始化,每次初始化的viewModel實例都是根據具體控制器的業務邏輯進行初始化,你如果直接訪問`self.viewModel`,而且直接訪問`MKJMainViewModel` 中的方法,肯定是不行的,除非你這麼做`(MKJMainViewModel *)self.viewModel`,這樣做就麻煩點了,其實可以用到上面的關鍵字`dynamic` 在子類裏面生成一個屬性,屬性名字和父類一樣,這樣就會出現上面的警告,告訴我們不會自動生成,由於是繼承來的,他會在父類生成實現,那麼爲了消除警告,你可以在m文件中的實現下面加上`@dynamic viewModel;`,也就是這個關鍵字的作用,告訴編譯器,不要警告了,getter和setter並不在此處,你運行的時候就知道從父類找了,那麼當你子類調用`self.viewModel` 的時候,你拿到的就是從基類的getter方法中拿出的實例對象</font>
<br/>
[參考博文](http://suree.org/2015/09/01/Dynamic-Synthesize/#more)

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