首頁 後端開發 C#.Net教程 Objective-C中的@dynamic

Objective-C中的@dynamic

Dec 13, 2016 am 09:09 AM
dynamic objective-c

一、@dynamic與@synthesize的區別

@property有兩個對應的詞,一個是@synthesize,一個是@dynamic。如果@synthesize和@dynamic都沒寫,那麼預設的就是@syntheszie var = _var;

 

@synthesize的語義是如果你沒有手動實現setter方法和getter方法,那麼編譯器會自動為你加上這兩個方法。

 

@dynamic告訴編譯器,屬性的setter與getter方法由使用者自己實現,不自動產生。 (當然對於readonly的屬性只需提供getter即可)。假如一個屬性被宣告為@dynamic var,然後你沒有提供@setter方法和@getter方法,編譯的時候沒問題,但是當程式運行到instance.var =someVar,由於缺setter方法會導致程式崩潰;或者當運行到someVar = var時,由於缺getter方法同樣會導致崩潰。編譯時沒問題,執行時才執行對應的方法,這就是所謂的動態綁定。

 

二、透過私有變數實現@dynamic的存取方法

1)Book.h

#import 

#import 

{

 @private

    __strong NSString *_name;

   (nonatomic, copy) NSString *name;

@property(nonatomic , copy) NSString *author;

@property(nonatomic, copy) NSString*version;

 

@end

@implementation Book

 

@dynamic name;

@dynamicauthor;

@synthesizeversion = _version;

 🠎 init];

    if(self)

{

    }

    return self;

}

 

- (NSString     {

        _name = @"you forgot inputbook name";

    }

    return _name;

}

 

- (void)setName:(NSString *)name_  NSLog(@"_name address:%p", _name);

}

 

- (NSString *)author

{

    if(nil == @"you forgot inputbook author";

    }

    return _author;

}

 

- (void)setAuthor:(NSString *)author

{

    _author = author

}

}

}程式碼可以看出,用@dynamic後,可以在存取方法中存取私有變數來賦值或取值。而@synthesize則直接用@synthesize var = _var;來讓屬性和私有變數直接等同起來。這就是二者在書寫形式上的差異。

 

三、透過訊息轉發來實現@dynamic的存取方法

若對於一個屬性使用了@dynamic var = _var,則編譯器立刻報錯。這樣你就無法像@synthesize那樣在var的setter方法和getter方法中使用_var,當然你更不能寫如下的setter方法和getter方法

- (void)setVar:(id)newVar

{

self.var =newVar;

}

 

- (void)var

{

   return self.var;崩潰。

 

這裡提供一個利用訊息轉發機制來實作@dynamic的setter和getter方法。

先上程式碼:

1)Book.h

#import 

 

@interface Bookpriv ary *_propertiesDict;

}

 

@property (nonatomic, copy) NSString *name;

@property (nonatomic, copy) HString*author)

@propertymic(nonato), @end

2) Book.m

#import "Book.h"

 

@implementation Book

@dynamic    name; // thesizeversion;

 

- (id)init

{

    self = [super init];

    ? *)methodSignatureForSelector:(SEL)選擇器

{

    NSString *sel = NSStringFromSelector(selector);

   

        return [NSMethod簽名signatureWithObjCTypes:"v@:@"];

    }

    其他

   

    }

}

 

- (void)forwardInitation: ( NSInitation *) 呼叫

{

    NSString *key = NSStringFromSelector([呼叫選擇器]);

    

        key= [ [ key substringWithRange:NSMakeRange(3, [key length]-4)] lowercaseString];

        NSString *obj;

       [調用 getArgument:&objatIndex:2] ࠦ;

其他    }

    

    {

        NSString * ;

       [調用setReturnValue:&obj];

   .h>

#import「書。h "

 

int main(int argc, const char * argv[])

{

 

  Book *book = [[Book alloc] init];

       書名= @ "c++ Primer";

       book.author = @"Stanley B.Lippman";

        book. ;

        NSLog (@ "%@", book.author);

        NSLog(@"%@", book.version);

   

1)在前面給程式加入訊息轉發功能,必須覆寫兩個方法,即methodSignatureForSelector:和forwardInitation:。了該訊息的物件。例一:- (NSString *)name

這個方法其實有兩個參數:self和_cmd。 self, _cmd和val。必須是SEL(就是_cmd的型別)

    C.從個參數開始,可以依照第三原方法的參數型別定義。參數高度是浮點數類型的,所以第三個參數型別就是f。

 

3)在main.m中有一段程式碼是book.name = @"c++ Primer";程式運行到這裡時,會去Book.m中找setName:這個賦值方法。方法,於是程式進入methodSignatureForSelector:中進行訊息轉發。

    這裡v@:@是什麼東西呢?實際上,這裡的第一個字元v代表函數的回傳類型是void,後面三個字元參考上面2)中的解釋就可以知道,分別是self, _cmd, name這三個參數的類型id, SEL, NSString。

    接著程序進入forwardInvocation方法。得到的key為方法名稱setName:,然後利用[invocationgetArgument:&objatIndex:2];取得到參數值,這裡是「c++ primer」。這裡的index為什麼要取2呢?如前面分析,第0個參數是self,第1個參數是_cmd,第2個參數才是方法後面帶的那個參數。

    最後利用一個變動字典來賦值。這樣就完成了整個setter流程。

 

4)在main.m中有一句程式碼是 NSLog(@"%@", book.name);,程式運作到這裡時,會去Book.m中尋找name這個取值方法 。但是Book.m裡並沒有這個取值方法,於是程式進入methodSignatureForSelector:中進行訊息轉發。執行完之後,以"@@:"作為方法簽名類型傳回。這裡第一個字元@代表函數傳回型別NSString,第二個字元@代表self的型別id,第三個字元:代表_cmd的型別SEL。

    接著程序進入forwardInvocation方法。得到的key為方法名稱name。最後根據這個key從字典取得對應的值,這樣就完成了整個getter過程。

 

5)注意,調試程式碼的過程,我們發現只有name和author的賦值和值進入methodSignatureForSelector:和forwardInvocation:這兩個方法。還有一個屬性version的賦值和值,並沒有進入methodSignatureForSelector:和forwardInvocation:這兩個方法。這是因為,version屬性被標識為@synthesize,編譯器自動會加上setVersion和version兩個方法,所以就不用訊息轉發了。

 

四、@dynamic在NSManagedObject的子類別中的使用

    @dynamic最常用的使用是在NSManagedObject中,此時不需要顯示程式設計setter和getter方法。原因是:@dynamic告訴編譯器不做處理,使編譯通過,其getter和setter方法會在運行時動態創建,由Core Data框架為此類屬性生成訪問方法。


本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

AI Hentai Generator

AI Hentai Generator

免費產生 AI 無盡。

熱門文章

R.E.P.O.能量晶體解釋及其做什麼(黃色晶體)
2 週前 By 尊渡假赌尊渡假赌尊渡假赌
倉庫:如何復興隊友
4 週前 By 尊渡假赌尊渡假赌尊渡假赌
Hello Kitty Island冒險:如何獲得巨型種子
3 週前 By 尊渡假赌尊渡假赌尊渡假赌

熱工具

記事本++7.3.1

記事本++7.3.1

好用且免費的程式碼編輯器

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

禪工作室 13.0.1

禪工作室 13.0.1

強大的PHP整合開發環境

Dreamweaver CS6

Dreamweaver CS6

視覺化網頁開發工具

SublimeText3 Mac版

SublimeText3 Mac版

神級程式碼編輯軟體(SublimeText3)

SpringBoot中如何使用Dynamic Datasource配置多重資料來源 SpringBoot中如何使用Dynamic Datasource配置多重資料來源 May 16, 2023 pm 07:07 PM

SpringBoot中如何使用Dynamic Datasource配置多重資料來源

Vue.js與Objective-C語言的集成,開發可靠的Mac應用的技巧和建議 Vue.js與Objective-C語言的集成,開發可靠的Mac應用的技巧和建議 Jul 30, 2023 pm 03:01 PM

Vue.js與Objective-C語言的集成,開發可靠的Mac應用的技巧和建議

如何使用Redis和Objective-C開發快取預熱功能 如何使用Redis和Objective-C開發快取預熱功能 Sep 22, 2023 am 08:24 AM

如何使用Redis和Objective-C開發快取預熱功能

Vue.js與Objective-C語言的集成,開發iOS應用的最佳實踐 Vue.js與Objective-C語言的集成,開發iOS應用的最佳實踐 Jul 30, 2023 pm 04:37 PM

Vue.js與Objective-C語言的集成,開發iOS應用的最佳實踐

如何使用Vue.js和Objective-C開發創新的iOS應用體驗的方法 如何使用Vue.js和Objective-C開發創新的iOS應用體驗的方法 Jul 30, 2023 pm 12:16 PM

如何使用Vue.js和Objective-C開發創新的iOS應用體驗的方法

如何使用Vue.js和Objective-C編寫可擴展的iOS應用 如何使用Vue.js和Objective-C編寫可擴展的iOS應用 Jul 29, 2023 pm 08:10 PM

如何使用Vue.js和Objective-C編寫可擴展的iOS應用

如何使用Redis和Objective-C開發即時地理位置追蹤功能 如何使用Redis和Objective-C開發即時地理位置追蹤功能 Sep 20, 2023 pm 12:46 PM

如何使用Redis和Objective-C開發即時地理位置追蹤功能

利用MySQL和Objective-C開發:如何實現資料模糊搜尋功能 利用MySQL和Objective-C開發:如何實現資料模糊搜尋功能 Jul 31, 2023 pm 05:53 PM

利用MySQL和Objective-C開發:如何實現資料模糊搜尋功能

See all articles