2012-08-09 8 views
5

के साथ दूरस्थ सर्वर खोज मैं एक ऐप पर काम कर रहा हूं जहां मैं एक सर्वर को दूरस्थ खोज बनाना चाहता हूं। मैं पुनर्प्राप्त डेटा को डेटाबेस में सहेजने के लिए RestKit चाहता हूं। मैं पहले स्थानीय खोज करता हूं (जो वर्तमान में काम करता है) तो मैं रिमोट सर्च करना चाहता हूं और फिर नए परिणामों के साथ टेबल व्यू अपडेट करना चाहता हूं।आईओएस, रीस्टकिट

मुझे दो समस्याएं आ रही हैं, 1. मेरी मैपिंग कैसा दिखना चाहिए और 2. जेसन दो अलग-अलग प्रकार की वस्तुओं के साथ एक सरणी देता है।

URL ऐसा दिखाई देगा:

search.json?search=[search string] 

JSON यह रिटर्न इस तरह दिखता है:

[ 
    { 
    "event": { 
     "id": 2, 
     [...] 
    }, 
    { 
    "news": { 
     "id": 16, 
     [...] 
    } 

घटना और खबर कहाँ वस्तुओं के दो प्रकार का है।

मेरे ऐप में मेरे पास तीन मॉडल हैं, पोस्ट (सार तत्व और सुपरक्लास) न्यूज़पोस्ट (पोस्ट करने के लिए उप-वर्ग) और ईवेंट (पोस्ट के लिए उप-वर्ग)।

मेरे मैपिंग इस तरह दिखता है:

RKManagedObjectMapping* newsMapping = [RKManagedObjectMapping mappingForClass:[NewsPost class] inManagedObjectStore:objectManager.objectStore]; 
newsMapping.primaryKeyAttribute = @"newsId"; 
newsMapping.rootKeyPath = @"news"; 
[newsMapping mapKeyPath:@"id" toAttribute:@"newsId"]; 

RKManagedObjectMapping *eventMapping = [RKManagedObjectMapping mappingForClass:[CalendarEvent class] inManagedObjectStore:objectManager.objectStore]; 
eventMapping.primaryKeyAttribute = @"calendarId"; 
eventMapping.rootKeyPath = @"calendars"; 
[eventMapping mapKeyPath:@"id" toAttribute:@"calendarId"]; 

// These two works. 
[objectManager.mappingProvider setObjectMapping:newsMapping forResourcePathPattern:@"/package_components/1/news"]; 
[objectManager.mappingProvider setObjectMapping:eventMapping forResourcePathPattern:@"/package_components/1/calendars"]; 

// I don't know how these should look/work. 
// Since the search word can change 
[objectManager.mappingProvider setObjectMapping:eventMapping forResourcePathPattern:@"/package_components/1/search\\.json?search="]; 
[objectManager.mappingProvider setObjectMapping:newsMapping forResourcePathPattern:@"/package_components/1/search\\.json?search="]; 

मेरे खोज कोड इस (स्थानीय खोज काम करता है) की तरह दिखता है:

- (void)setUpSearch 
{ 
    if (self.searchField.text != nil) { 

     [self.posts removeAllObjects]; 
     [self.events removeAllObjects]; 
     [self.news removeAllObjects]; 

     // Search predicates. 
     // Performs local search. 
     NSPredicate *contactNamePredicate = [NSPredicate predicateWithFormat:@"contactName contains[cd] %@", self.searchField.text]; 
     NSPredicate *contactDepartmentPredicate = [NSPredicate predicateWithFormat:@"contactDepartment contains[cd] %@", self.searchField.text]; 
     [...] 

     NSArray *predicatesArray = [NSArray arrayWithObjects:contactNamePredicate, contactDepartmentPredicate, contactEmailPredicate, contactPhonePredicate, linkPredicate, titlePredicate, nil]; 

     NSPredicate *predicate = [NSCompoundPredicate orPredicateWithSubpredicates:predicatesArray]; 

     self.posts = [[Post findAllWithPredicate:predicate] mutableCopy]; 

     if (self.posts.count != 0) { 
      self.noResultsLabel.hidden = YES; 
      for (int i = 0; i < self.posts.count; i++) { 
       Post * post = [self.posts objectAtIndex:i]; 
       if (post.calendarEvent == YES) { 
        [self.events addObject:post]; 
       } else { 
        [self.news addObject:post]; 
       } 
      } 
     } 

     // reload the table view 
     [self.tableView reloadData]; 

     [self performRemoteSearch]; 
    } 
} 

- (void)search 
{  
    [self setUpSearch]; 
    [self hideKeyboard]; 
    [self performRemoteSearch]; 
} 


- (void)performRemoteSearch 
{ 
    // Should load the objects from JSON  
    // Note that the searchPath can vary depending on search text. 
    NSString *searchPath = [NSString stringWithFormat:@"/package_components/1/search.json?search=%@", self.searchField.text]; 
    RKObjectManager *objectManager = [RKObjectManager sharedManager]; 
    [objectManager loadObjectsAtResourcePath:searchPath delegate:self]; 
} 

- (void)objectLoader:(RKObjectLoader*)objectLoader didLoadObjects:(NSArray*)objects 
{ 
    // This never gets called. 

    // Should update my arrays and then update the tableview, but it never gets called. 
    // Instead I get Error Domain=org.restkit.RestKit.ErrorDomain Code=1001 "Could not find an object mapping for keyPath: '' 
} 

मैं कैसे कर सकता है चाहिए या पर कोई सुझावों बहुत सराहना की जाएगी।

+0

हाय, मैं इस प्रश्न को देने का प्रयास कर रहा हूं। 1. क्या आप किसी भी तरह से JSON के प्रारूप को बदलने में सक्षम हैं? मैं जानना चाहता हूं कि क्या आप प्रत्येक परिणाम के लिए रूट कुंजी पथ जोड़ सकते हैं (जो इसे बहुत सरल बना देगा)। 2. आप समाचार और घटना के लिए एनएसएमएनेज्ड ऑब्जेक्ट का उपयोग कर रहे हैं। क्या आप मैपिंग को उपयोगकर्ता खोज पर कॉर्डटा में सहेजना चाहते हैं? –

+0

हाय, हाँ, यदि आवश्यक हो तो मैं JSON बदल सकता हूं। और, हां, जब उपयोगकर्ता खोज करता है तो मैं स्थानीय रूप से परिणामों को कैश और सहेजना चाहता हूं। – Anders

+0

मुझे बताएं कि क्या उत्तर आपके लिए काम करता है। –

उत्तर

3

मैंने पहले प्रबंधित ऑब्जेक्ट्स का उपयोग नहीं किया है, लेकिन यहां पहली बात यह है कि ऑब्जेक्ट मैपिंग और नेटवर्क अनुरोध पर रीस्टकिट लॉग को सक्रिय करना है ताकि आप जांच सकें कि सर्वर से क्या शेष है और मैपिंग कैसे काम कर रही है।

//This can be added in your app delegate 
RKLogConfigureByName("RestKit/Network", RKLogLevelDebug); 
RKLogConfigureByName("RestKit/ObjectMapping", RKLogLevelTrace); 

दूसरे स्थान पर, अपने खोज पथ परिवर्तन आपके JSON करने के लिए और कहा कि अनुसार, मुझे लगता है कि बजाय कुंजी पथ संसाधन पथ पैटर्न के लिए मानचित्रण का उपयोग करने के लिए बेहतर है। की तरह अपने डेटा लोड

RKObjectMapping* articleMapping = [RKObjectMapping mappingForClass:[Article class]]; 
[articleMapping mapKeyPath:@"title" toAttribute:@"title"]; 
[articleMapping mapKeyPath:@"body" toAttribute:@"body"]; 
[articleMapping mapKeyPath:@"author" toAttribute:@"author"]; 
[articleMapping mapKeyPath:@"publication_date" toAttribute:@"publicationDate"]; 

[[RKObjectManager sharedManager].mappingProvider setMapping:articleMapping forKeyPath:@"articles"]; 

और फिर:

- (void)loadArticles { 
    [[RKObjectManager sharedManager] loadObjectsAtResourcePath:@"/articles" delegate:self]; 
} 

यह करने के लिए अन्य तरीके से वस्तु से मैप करने के लिए है, इसलिए RestKit पहचान लेता है, तो आप इस उदाहरण की तरह, कुंजी द्वारा मैप करने के लिए कोशिश करनी चाहिए वस्तु का प्रकार और मैपिंग करता है और आप किसी भी पथ के लिए अनुरोध करते हैं।

यदि आपके कोई प्रश्न हैं तो कृपया एक टिप्पणी छोड़ दें और मैं आवश्यकतानुसार अपना उत्तर सुधार सकता हूं।

+0

धन्यवाद, मैं कल इसका परीक्षण करूंगा। – Anders

1

मैं एक इनाम से पहले के साथ एक सवाल का जवाब देने की कोशिश की कभी नहीं किया है, मुझे कुछ हाल ही में काम से एक उपयोगी जवाब देने की कोशिश करते हैं =)

1. कैसे मेरे मानचित्रण जैसे

से दिखना चाहिए आपका कोड, सब ठीक दिखता है। क्या वस्तुओं की कोई घोंसला है? क्या आपको सर्वर पर वापस पोस्ट करने के लिए क्रमबद्ध करने की आवश्यकता है?

2. जेसन दो अलग-अलग प्रकार की वस्तुओं के साथ एक सरणी देता है।

क्या आपके गुण समान हैं (यानी।घटना में एक शीर्षक है, घटना की तारीख है) कोई आश्चर्य नहीं है? यदि नहीं, तो आपको dynamic nesting का उपयोग करना होगा।

यदि कोई संसाधन पथ (यानी आपका खोज पथ) विभिन्न ऑब्जेक्ट्स (आपके मामले) के साथ संग्रह प्राप्त करता है, तो आपको वस्तुओं को लोड करने के लिए dynamic object mapping का उपयोग करना होगा।

चूंकि आप JSON संरचना को संपादित कर सकते हैं, इसलिए RestKit पर लीवरेज करके चीजें सरल हो सकती हैं।

- सुनिश्चित करें कि JSON के पास दो अलग-अलग प्रकार की वस्तुओं के लिए root_key_path है।

पुराने प्रयोग और कुछ googling से, RestKit उचित ऑब्जेक्ट्स के साथ एक जेसन आउटपुट को सही तरीके से मैप कर सकता है यदि उनके पास उचित रूटकेपैथ हैं। जेएसओएन के परिणामस्वरूप एक मोटा संरचना होना चाहिए:

{ 
    "news" : [ 
    { 
     "id" : 1, 
     "title" : "Mohawk guy quits" 
    }, 
    { 
     "id" : 2, 
     "title" : "Obama gets mohawk" 
    } 
    ], 
    "events" : [ 
    { 
     "id" : 1, 
     "name" : "testing" 
    }, 
    { 
     "id" : 2, 
     "name" : "testing again" 
    } 
    ] 
} 

मुझे यकीन नहीं है कि ऊपर 100% सही है। आप केवल एपीआई रिटर्न न्यूज बनाकर प्रयोग कर सकते हैं, अगर यह काम करता है, तो मिश्रण डेटा को मिश्रण में जोड़ना।

- सर्वर से वस्तुओं

// Make a NS dictionary and use stringByAppendingQueryParameters 

NSDictionary *searchParams = [NSDictionary dictionaryWithKeysAndObjects: 
           @"query",@"myQuery", 
           @"location",@"1.394168,103.895473", 
           nil]; 

[[RKObjectManager sharedManager] loadObjectsAtResourcePath:[@"/path/to/resource.json" stringByAppendingQueryParameters:searchParams] delegate:objectLoaderDelegate]; 

लोड - संभाल "असली" खोज करते समय अपने objectLoader प्रतिनिधि

में अगर यह काम किया, वस्तुओं अपने CoreData संस्थाओं के लिए मैप किया जाना चाहिए। आप ऊपर पोस्ट की गई NSPredicate विधि का उपयोग करके स्थानीय खोज कर सकते हैं।

मैं डिजाइन पैटर्न पसंद करता हूं जहां सर्वर से डेटा प्राप्त करने और मानचित्र बनाने के लिए रेस्टकिट loadObjects... का उपयोग करता है, बाकी की प्रक्रिया स्थानीय रूप से की जाती है। यह decoupling चीजों को और अधिक "ऐप की तरह" बनाता है। आप NSPredicates का उपयोग कर हेरफेर के अन्य रूप कर सकते हैं।

- (void)objectLoader:(RKObjectLoader*)objectLoader didLoadObjects:(NSArray*)objects { 
    // Do some processing here on the array of returned objects or cede control to a method that 
    // you've built for the search, like the above method. 
} 

एक उदाहरण, खोज उपयोग के मामले रेस्तरां पास है अगर, यह शायद वर्तमान अक्षांश/देशांतर के भीतर सभी रेस्तरां लोड करने के लिए समझ बनाने, और फिर CoreData का उपयोग कर नाम से स्थानीय छानने प्रदर्शन करते हैं। आपका सर्वर आपको दिल देगा।

मुझे बताएं और मैं आगे जवाब को बेहतर बनाने की कोशिश करूंगा।

+0

आपके उत्तर के लिए धन्यवाद, और मेरे देर के उत्तर के लिए खेद है। मुझे वास्तव में कुछ मामूली संशोधनों के साथ @clopez उत्तर का उपयोग करके काम करने के लिए मिला। – Anders