2009-05-06 12 views
19

से मुझे लगता है कि इस बेवकूफ सवाल यह है कि है, लेकिन मैं वैसे भी पूछना होगा ...instantiating कस्टम वर्ग NSDictionary

मैं NSDictionary वस्तुओं जिसका कुंजी का एक संग्रह है/मान युग्म मैं एक कस्टम वर्ग के अनुरूप बनाया है, इसे MyClass पर कॉल करें। MyClass * instance = [ मानचित्र NSDictionary गुणों को MyClass]; पर मूल रूप से कुछ करने के लिए मेरे लिए कोई आसान या "सर्वोत्तम अभ्यास" विधि है? मुझे एहसास है कि मुझे NSCoding या NSKeyedUnarchiver के साथ कुछ करने की ज़रूरत है, लेकिन इसके माध्यम से इसके माध्यम से ठोकर खाने की बजाय, मुझे लगता है कि कोई मुझे सही दिशा में इंगित करने में सक्षम हो सकता है।

उत्तर

26

ThesetValu esForKeysWithDictionary: विधि, साथ -DictionaryWithValuesForKeys:, जो आप उपयोग करना चाहते हैं।

उदाहरण:

// In your custom class 
+ (id)customClassWithProperties:(NSDictionary *)properties { 
    return [[[self alloc] initWithProperties:properties] autorelease]; 
} 

- (id)initWithProperties:(NSDictionary *)properties { 
    if (self = [self init]) { 
     [self setValuesForKeysWithDictionary:properties]; 
    } 
    return self; 
} 

// ...and to easily derive the dictionary 
NSDictionary *properties = [anObject dictionaryWithValuesForKeys:[anObject allKeys]]; 
+2

यह बहुत आसान है, और setValuesForPropertiesWithKeys जाने का रास्ता है। यह वही करता है जो मेरा कोड करता है, और यह बनाया गया है! अच्छा लगता है। –

+0

यह एक शानदार तरीका है। Objc_ * एपीआई के संयोजन के साथ इसका उपयोग करके, आप एक ऑटो-सीरियलाइजिंग क्लास बना सकते हैं (ताकि आप उन बोझिल-इनिट विथकोडर को लिखना बंद कर सकें: और -कोडकथकोडर: विधियां) – retainCount

+0

बहुत बढ़िया। यह काम में आने वाला है। –

3

यह मानते हुए कि अपने वर्ग Key-Value Coding प्रोटोकॉल के अनुरूप है, तो आपको निम्न इस्तेमाल कर सकते हैं: (सुविधा के लिए NSDictionary पर एक वर्ग के रूप में परिभाषित):

// myNSDictionaryCategory.h: 
@interface NSDictionary (myCategory) 
- (void)mapPropertiesToObject:(id)instance 
@end 


// myNSDictionaryCategory.m: 
- (void)mapPropertiesToObject:(id)instance 
{ 
    for (NSString * propertyKey in [self allKeys]) 
    { 
     [instance setValue:[self objectForKey:propertyKey] 
        forKey:propertyKey]; 
    } 
} 

और यहाँ कैसे आप है इसका उपयोग करेंगे:

#import "myNSDictionaryCategory.h" 
//... 
[someDictionary mapPropertiesToObject:someObject]; 
+0

धन्यवाद। यही वह था जिसे मैं ढूंढ रहा था। :) – LucasTizma

+0

आपका स्वागत है! –

+2

ऐसा लगता है कि रेड का एक बेहतर जवाब है। मैं अनुशंसा करता हूं कि आप स्वीकृत उत्तर को उसके :) –

6

वहाँ NSObject पर कोई allKeys है।

NSObject + PropertyArray.h

@interface NSObject (PropertyArray) 
- (NSArray *) allKeys; 
@end 

NSObject + PropertyArray.m

#import <objc/runtime.h> 

@implementation NSObject (PropertyArray) 
- (NSArray *) allKeys { 
    Class clazz = [self class]; 
    u_int count; 

    objc_property_t* properties = class_copyPropertyList(clazz, &count); 
    NSMutableArray* propertyArray = [NSMutableArray arrayWithCapacity:count]; 
    for (int i = 0; i < count ; i++) { 
     const char* propertyName = property_getName(properties[i]); 
     [propertyArray addObject:[NSString stringWithCString:propertyName encoding:NSUTF8StringEncoding]]; 
    } 
    free(properties); 

    return [NSArray arrayWithArray:propertyArray]; 
} 
@end 

उदाहरण::

#import "NSObject+PropertyArray.h" 

... 

MyObject *obj = [[MyObject alloc] init]; 
obj.a = @"Hello A"; //setting some values to attributes 
obj.b = @"Hello B"; 

//dictionaryWithValuesForKeys requires keys in NSArray. You can now 
//construct such NSArray using `allKeys` from NSObject(PropertyArray) category 
NSDictionary *objDict = [obj dictionaryWithValuesForKeys:[obj allKeys]]; 

//Resurrect MyObject from NSDictionary using setValuesForKeysWithDictionary 
MyObject *objResur = [[MyObject alloc] init]; 
[objResur setValuesForKeysWithDictionary:objDict]; 
+0

तुम भी इस श्रेणी में एक और तरीका जोड़ सकते हैं लिखना चाहिए है: - (NSDictionary *) dictionaryWithValuesForKeys { वापसी [आत्म dictionaryWithValuesForKeys: [आत्म allKeys]]; } – jpalten

0
आप नीचे दिए गए जैसे NSObject पर एक अतिरिक्त श्रेणी बनाने की आवश्यकता होगी

यदि आप इस तरह की चीजें कर रहे हैं तो आप जेएसओएन से निपट रहे हैं और आपको शायद मैटल 012 पर एक नज़र डालना चाहिएhttps://github.com/Mantle/Mantle

फिर आप एक सुविधाजनक तरीका dictionaryValue

[anObject dictionaryValue]; 
0

बस श्रेणी NSObject के लिए अपने कस्टम वस्तुओं से dictionaryRepresentation प्राप्त करने के लिए (केवल JSON क्रमबद्धता में उपयोग करते हुए मेरे मामले में) जोड़ने के मिल जाएगा:

// NSObject+JSONSerialize.h 
#import <Foundation/Foundation.h> 

@interface NSObject(JSONSerialize) 

- (NSDictionary *)dictionaryRepresentation; 

@end 

// NSObject+JSONSerialize.m 
#import "NSObject+JSONSerialize.h" 
#import <objc/runtime.h> 

@implementation NSObject(JSONSerialize) 

+ (instancetype)instanceWithDictionary:(NSDictionary *)aDictionary { 
    return [[self alloc] initWithDictionary:aDictionary]; 
} 

- (instancetype)initWithDictionary:(NSDictionary *)aDictionary { 
    aDictionary = [aDictionary clean]; 

    self.isReady = NO; 

    for (NSString* propName in [self allPropertyNames]) { 
     [self setValue:aDictionary[propName] forKey:propName]; 
    } 

    //You can add there some custom properties with wrong names like "id" 
    //[self setValue:aDictionary[@"id"] forKeyPath:@"objectID"]; 
    self.isReady = YES; 

    return self; 
} 

- (NSDictionary *)dictionaryRepresentation { 
    NSMutableDictionary *result = [NSMutableDictionary dictionary]; 
    NSArray *propertyNames = [self allPropertyNames]; 

    id object; 
    for (NSString *key in propertyNames) { 
     object = [self valueForKey:key]; 
     if (object) { 
      [result setObject:object forKey:key]; 
     } 
    } 

    return result; 
} 

- (NSArray *)allPropertyNames { 
    unsigned count; 
    objc_property_t *properties = class_copyPropertyList([self class], &count); 

    NSMutableArray *rv = [NSMutableArray array]; 

    unsigned i; 
    for (i = 0; i < count; i++) { 
     objc_property_t property = properties[i]; 
     NSString *name = [NSString stringWithUTF8String:property_getName(property)]; 
     [rv addObject:name]; 
    } 
    //You can add there some custom properties with wrong names like "id" 
    //[rv addObject:@"objectID"]; 
    //Example use inside initWithDictionary: 
    //[self setValue:aDictionary[@"id"] forKeyPath:@"objectID"]; 

    free(properties); 

    return rv; 
} 

@end 

इसके अलावा, आप देख सकते हैं कि मेरा समाधान कस्टम ऑब्जेक्ट्स के साथ नेस्टेड ऑब्जेक्ट्स या सरणी के साथ काम नहीं करेगा। Arrays के लिए - dictionaryRepresentation विधि में कोड की रेखाओं को बदलें:

if (object) { 
     if ([object isKindOfClass:[NSArray class]]) { 
      @autoreleasepool { 
       NSMutableArray *array = [NSMutableArray array]; 
       for (id item in (NSArray *)object) { 
        [array addObject:[item dictionaryRepresentation]]; 
       } 

       [result setObject:array forKey:key]; 
      } 
     } else { 
      [result setObject:object forKey:key]; 
     } 
    } 
संबंधित मुद्दे