2012-06-24 10 views
5

मैं अपने पहले रेस्टकिट ऐप पर काम कर रहा हूं, और मैं स्थानीय कैशिंग के लिए कोरडाटा का उपयोग करता हूं। इसमें मेरे पास < < --- >> श्रेणी के बीच कई से अधिक संबंध हैं। रिश्ते को पदों और श्रेणियों कहा जाता है।कई मैपिंग को रीस्टकिट करें, कैसे करें?

मेरे पोस्ट में JSON कॉल मुझे इस तरह की श्रेणियों के लिए आईडी मिलती है: {"post": [...] "categories":[1,4] [...], जहां 1 और 4 आईडी हैं।

मैं एक कस्टम Post मॉडल उद्देश्य यह है कि NSManagedObject से विरासत है, उस में मैं श्रेणियों के लिए एक संपत्ति है, इस तरह है:

@interface Post : NSManagedObject 

[...] 
@property (nonatomic, retain) NSSet *categories; 
[...] 

मैं एक कस्टम श्रेणी मॉडल वस्तु में एक ही बात करते हैं।

मेरे मैपिंग वर्तमान में इस तरह दिखता है: '[<__NSCFNumber 0x6c625e0> valueForUndefinedKey:]: this class is not key value coding-compliant for the key id.'

मैं वास्तव में अगर कोई मुझे कैसे इस रिश्ते को मैप करने पर कोई सुराग दे सकता है की सराहना करेंगे:

RKManagedObjectMapping *categoryMapping = [RKManagedObjectMapping mappingForClass:[Category class] inManagedObjectStore:objectManager.objectStore]; 
categoryMapping.primaryKeyAttribute = @"categoryId"; 
categoryMapping.rootKeyPath = @"categories"; 
[categoryMapping mapKeyPath:@"id" toAttribute:@"categoryId"]; 
[categoryMapping mapKeyPath:@"name" toAttribute:@"name"]; 
[...] 


RKManagedObjectMapping* postMapping = [RKManagedObjectMapping mappingForClass:[Post class] inManagedObjectStore:objectManager.objectStore]; 

postMapping.primaryKeyAttribute = @"postId"; 
postMapping.rootKeyPath = @"post"; 
[postMapping mapKeyPath:@"id" toAttribute:@"postId"]; 
[...] 
[postMapping mapKeyPath:@"created_at" toAttribute:@"createdAt"]; 
[...] 
// Categories many-to-many. 
[postMapping mapKeyPath:@"categories" toRelationship:@"categories" withMapping:categoryMapping]; 

जब मैं इस चलाने मैं त्रुटि मिलती है।

उत्तर

2

वहां त्रुटि है क्योंकि आपका JSON प्रत्येक श्रेणी को प्राथमिक कुंजी के रूप में देता है, यानी: एनएसएनंबर। लेकिन आपकी मैपिंग एक नेस्टेड ऑब्जेक्ट की अपेक्षा करती है (जिसे एक केवीसी ऑब्जेक्ट में बदल दिया जाएगा)। जब आपका नक्शा केवीसी ऑब्जेक्ट (जो वास्तव में एनएसएनंबर) पर संपत्ति "आईडी" तक पहुंचने का प्रयास करता है, तो यह इस तरह दुर्घटनाग्रस्त हो जाएगा।

मुझे यकीन है कि अगर यह काम करेगा नहीं कर रहा हूँ, लेकिन आप कुछ इस तरह की कोशिश कर सकते हैं: आप [: withObjectForPrimaryKeyAttribute: RKManagedObjectMapping connectRelationship] का प्रयोग करेंगे

RKManagedObjectMapping* categoryMapping = //something 
categoryMapping.primaryKeyAttribute = @"categoryId"; 
[categoryMapping mapKeyPath: @"" toAttribute: @"categoryId"]; 

[..] 

[postMapping mapKeyPath: @"categories" toRelationship: @"categories" withMapping: categoryMapping]; 

आम तौर पर, विधि, लेकिन मैं नहीं जानता कि अगर यह कई से अधिक रिश्तों पर काम करेगा। ऐसा करने के लिए आपको स्रोत कोड को संशोधित करना पड़ सकता है। देखने के लिए कोड अंदर है [RKManagedObjectMappingOperation कनेक्ट रिश्ते:]।

अन्यथा, यदि संभव हो तो मैं सुझाव दूंगा कि आप अपना JSON स्रोत बदल दें ताकि श्रेणियों की सरणी इस तरह हो: "श्रेणियां": [{"श्रेणी आईडी: 1}, {" categoryID ": 4}]। यदि स्रोत नहीं है बदलने के लिए संभव है, आप डेटा मैन्युअल प्रतिनिधि तरीकों या RKObjectLoader एक्सटेंशन का उपयोग कर संशोधित कर सकते हैं मैं नीचे दे दिया है:

typedef void(^RKObjectLoaderWillMapDataBlock)(id* mappableData); 

@interface RKObjectLoader (Extended) 

@property (nonatomic, copy) RKObjectLoaderWillMapDataBlock onWillMapData; 

@end 

मीटर

#import "RKObjectLoader+Extended.h" 

#import <objc/runtime.h> 

NSString* kOnWillMapDataKey = @"onWillMapData"; 

@implementation RKObjectLoader (Extended) 

- (RKObjectLoaderWillMapDataBlock) onWillMapData { 
    return objc_getAssociatedObject(self, &kOnWillMapDataKey); 
} 

- (void) setOnWillMapData:(RKObjectLoaderWillMapDataBlock) block { 
    objc_setAssociatedObject(self, &kOnWillMapDataKey, block, OBJC_ASSOCIATION_COPY); 
} 

- (RKObjectMappingResult*)mapResponseWithMappingProvider:(RKObjectMappingProvider*)mappingProvider toObject:(id)targetObject inContext:(RKObjectMappingProviderContext)context error:(NSError**)error { 
    id<RKParser> parser = [[RKParserRegistry sharedRegistry] parserForMIMEType:self.response.MIMEType]; 
    NSAssert1(parser, @"Cannot perform object load without a parser for MIME Type '%@'", self.response.MIMEType); 

    // Check that there is actually content in the response body for mapping. It is possible to get back a 200 response 
    // with the appropriate MIME Type with no content (such as for a successful PUT or DELETE). Make sure we don't generate an error 
    // in these cases 
    id bodyAsString = [self.response bodyAsString]; 
    RKLogTrace(@"bodyAsString: %@", bodyAsString); 
    if (bodyAsString == nil || [[bodyAsString stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]] length] == 0) { 
     RKLogDebug(@"Mapping attempted on empty response body..."); 
     if (self.targetObject) { 
      return [RKObjectMappingResult mappingResultWithDictionary:[NSDictionary dictionaryWithObject:self.targetObject forKey:@""]]; 
     } 

     return [RKObjectMappingResult mappingResultWithDictionary:[NSDictionary dictionary]]; 
    } 

    id parsedData = [parser objectFromString:bodyAsString error:error]; 
    if (parsedData == nil && error) { 
     return nil; 
    } 

    // Allow the delegate to manipulate the data 
    if ([self.delegate respondsToSelector:@selector(objectLoader:willMapData:)]) { 
     parsedData = AH_AUTORELEASE([parsedData mutableCopy]); 
     [(NSObject<RKObjectLoaderDelegate>*)self.delegate objectLoader:self willMapData:&parsedData]; 
    } 

    if(self.onWillMapData) { 
     parsedData = AH_AUTORELEASE([parsedData mutableCopy]); 
     self.onWillMapData(&parsedData); 
    } 

    RKObjectMapper* mapper = [RKObjectMapper mapperWithObject:parsedData mappingProvider:mappingProvider]; 
    mapper.targetObject = targetObject; 
    mapper.delegate = (id<RKObjectMapperDelegate>)self; 
    mapper.context = context; 
    RKObjectMappingResult* result = [mapper performMapping]; 

    // Log any mapping errors 
    if (mapper.errorCount > 0) { 
     RKLogError(@"Encountered errors during mapping: %@", [[mapper.errors valueForKey:@"localizedDescription"] componentsJoinedByString:@", "]); 
    } 

    // The object mapper will return a nil result if mapping failed 
    if (nil == result) { 
     // TODO: Construct a composite error that wraps up all the other errors. Should probably make it performMapping:&error when we have this? 
     if (error) *error = [mapper.errors lastObject]; 
     return nil; 
    } 

    return result; 
} 

@end 
+0

धन्यवाद, बदलने का फैसला किया JSON 'श्रेणियों" के लिए: [{"category_id": 1}, {"category_id": 4}] ', क्या आप जानते हैं कि मुझे तालिका में कैसे और कब पॉप्युलेट करना चाहिए? मैं वर्तमान में केवल श्रेणियां लाता हूं। धन्यवाद! – Anders

+0

जॉइन टेबल क्या है? यह वास्तव में एक और सवाल है। –

+0

हाँ, धन्यवाद। एक जॉइन टेबल दो से कई इकाइयों के बीच तालिका है, जहां दो तालिकाओं की प्राथमिक कुंजी संग्रहीत की जाती है। जब मैं पोस्ट लोड करता हूं तो यह वास्तव में इस तालिका में पॉप्युलेट करता है, लेकिन फिर यह किसी कारण से मेरे श्रेणी मॉडल में नई पंक्तियां भी बनाता है। शायद उस मुद्दे के लिए एक और सवाल पूछेंगे। लेकिन JSON को बदलने में मदद मिली, कोई त्रुटि नहीं। धन्यवाद! – Anders