Objective-C的反射機制

來源:互聯網
上載者:User

標籤:http   io   ar   os   使用   sp   for   java   strong   

從JSONModel看Objective-C的反射機制前言

移動互聯時代,JSON作為一種資料轉送格式幾乎隨處可見。作為iOS開發人員,收到一串JSON字串要怎麼處理?我想多數情況下是需要將它轉成自訂的NSObject對象再使用,對於這個轉換的過程,大部分人是這麼做的:

1234567
NSDictionary* json = (fetch from Internet) ...User* user=[[User alloc] init];user.userId =[json objectForKey:@"userId"];user.nick= [json objectForKey:@"nick"];user.image = [json objectForKey:@"image"];user.age = [json objectForKey:@"age"];...

這樣的代碼沒錯,但也絕對說不上優雅,model裡面的屬性越多,冗餘的代碼量也相應越多。對於這個問題,自然是有更好的解決方案,比如說這樣:

12
NSError* err = nil;User* user = [[User alloc] initWithDictionary:json error:&err];

兩行代碼足矣,當然,實現這個功能,實際上是把很多背後的工作交給JSONModel這個開源包去做了。至於其實現原理,則主要是基於Objective-C Runtime的反射機制。

關於反射

《Thinking in Java》中將反射稱解釋為運行時的類資訊,說白了就是這個類資訊在編譯的時候是未知的,需要在程式運行期間動態擷取,而這正是我們之前試圖去解決的問題。對於從網路上擷取到的一段JSON字串,在代碼編譯期間當然是無法知曉的。雖然這裡說的是Java語言,但是對於Objective-C,這種反射機制也是同樣支援的。

JSONModel中的實現

打斷點記錄了下JSONModel這個類中的方法調用順序如下:

對象屬性的擷取則主要在最後一個inspectProperties方法

以下是inspectProperties方法的程式碼片段:

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556
···//inspects the class, get‘s a list of the class properties-(void)__inspectProperties{    //JMLog(@"Inspect class: %@", [self class]);        NSMutableDictionary* propertyIndex = [NSMutableDictionary dictionary];        //temp variables for the loops    Class class = [self class];    NSScanner* scanner = nil;    NSString* propertyType = nil;        // inspect inherited properties up to the JSONModel class    while (class != [JSONModel class]) {        //JMLog(@"inspecting: %@", NSStringFromClass(class));                unsigned int propertyCount;        objc_property_t *properties = class_copyPropertyList(class, &propertyCount);                //loop over the class properties        for (unsigned int i = 0; i < propertyCount; i++) {            JSONModelClassProperty* p = [[JSONModelClassProperty alloc] init];            //get property name            objc_property_t property = properties[i];            const char *propertyName = property_getName(property);            p.name = [NSString stringWithUTF8String:propertyName];                        //JMLog(@"property: %@", p.name);                        //get property attributes            const char *attrs = property_getAttributes(property);            NSString* propertyAttributes = [NSString stringWithUTF8String:attrs];                        if ([propertyAttributes hasPrefix:@"Tc,"]) {                //mask BOOLs as structs so they can have custom convertors                p.structName = @"BOOL";            }                        scanner = [NSScanner scannerWithString: propertyAttributes];                        //JMLog(@"attr: %@", [NSString stringWithCString:attrs encoding:NSUTF8StringEncoding]);            [scanner scanUpToString:@"T" intoString: nil];            [scanner scanString:@"T" intoString:nil];···//finally store the property index in the static property indexobjc_setAssociatedObject(self.class,                         &kClassPropertiesKey,                         [propertyIndex copy],                         OBJC_ASSOCIATION_RETAIN // This is atomic                         );

在這邊可以看到基本步驟如下

  1. 通過調用自身的class方法擷取當前類的中繼資料資訊
  2. 通過runtime的 class_copyPropertyList 方法取得當前類的屬性列表,以指標數組的形式返回
  3. 遍曆指標數組,通過property_getName擷取屬性名稱,property_getAttributes擷取屬性類型
  4. 使用NSScanner來掃描屬性類型字串,將類似如下的形式"[email protected]"NSNumber",&,N,V_id",處理成NSNumber,逐個屬性迴圈處理
  5. 將所有處理好的資料放入propertyIndex這個字典中
  6. 通過objc_setAssociatedObject將這些資料關聯到kClassPropertiesKey

使用時在properties方法中這樣取出屬性資料:

1234567891011121314
//returns a list of the model‘s properties-(NSArray*)__properties__{    //fetch the associated object    NSDictionary* classProperties = objc_getAssociatedObject(self.class, &kClassPropertiesKey);    if (classProperties) return [classProperties allValues];    //if here, the class needs to inspect itself    [self __setup__];        //return the property list    classProperties = objc_getAssociatedObject(self.class, &kClassPropertiesKey);    return [classProperties allValues];}

以上就是JSONModel中使用反射機制實現的類屬性擷取過程,相比常見的逐個取值賦值的方式,這種方法在代碼上的確簡潔優雅了很多,特別是對於使用的類屬性比較複雜的情況,免除了很多不必要的代碼。

Objective-C的反射機制

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.