CoreData और REST वेब सेवा को एक साथ समकालित कैसे करें और उसी समय UI में किसी भी REST त्रुटियों को ठीक से प्रचारित करें


85

अरे, मैं यहाँ हमारे ऐप के लिए मॉडल लेयर पर काम कर रहा हूँ।

कुछ आवश्यकताएँ इस प्रकार हैं:

  1. यह iPhone OS 3.0+ पर काम करना चाहिए।
  2. हमारे डेटा का स्रोत एक RESTful Rails एप्लिकेशन है।
  3. हमें कोर डेटा का उपयोग करके स्थानीय रूप से डेटा को कैश करना चाहिए।
  4. क्लाइंट कोड (हमारे UI नियंत्रक) को किसी भी नेटवर्क सामान के बारे में कम से कम ज्ञान होना चाहिए और कोर डेटा एपीआई के साथ मॉडल को क्वेरी / अपडेट करना चाहिए।

मैंने एक सर्वर-चालित उपयोगकर्ता अनुभव के निर्माण पर WWDC10 सत्र 117 की जाँच की है, कुछ समय वस्तुनिष्ठ संसाधन , कोर संसाधन , और RestfulCoreData चौखटे की जाँच में बिताया है ।

ऑब्जेक्टिव रिसोर्स फ्रेमवर्क अपने आप में कोर डेटा से बात नहीं करता है और यह केवल एक REST क्लाइंट कार्यान्वयन है। कोर संसाधन और RestfulCoreData आप अपने कोड में कोर डेटा से बात करते हैं और वे मॉडल परत पर पृष्ठभूमि में सभी नट और बोल्ट को हल।

सभी अब तक ठीक लग रहे हैं और शुरू में मैं या तो कोर रिसोर्स या रेस्टफुल कोरडाटा उपरोक्त सभी आवश्यकताओं को कवर करूंगा, लेकिन ... उनमें से कोई भी एक चीज नहीं है जो सही ढंग से हल करने के लिए प्रतीत होती है:

  1. सर्वर पर स्थानीय अपडेट सहेजते समय मुख्य थ्रेड को ब्लॉक नहीं किया जाना चाहिए।
  2. यदि बचत संचालन विफल हो जाता है तो त्रुटि को UI में प्रचारित किया जाना चाहिए और स्थानीय कोर डेटा स्टोरेज में कोई परिवर्तन नहीं किए जाने चाहिए।

जब आप - (BOOL)save:(NSError **)errorअपने प्रबंधित ऑब्जेक्ट संदर्भ पर कॉल करते हैं, तो कोर संसाधन सर्वर के लिए अपने सभी अनुरोधों को जारी करने के लिए होता है और इसलिए सर्वर को अंतर्निहित अनुरोधों का एक सही NSError उदाहरण प्रदान करने में सक्षम होता है जो किसी भी तरह से विफल हो जाता है। लेकिन यह कॉलिंग थ्रेड को तब तक ब्लॉक करता है जब तक कि सेव ऑपरेशन खत्म नहीं हो जाता। असफल।

RestfulCoreData आपके -save:कॉल को बरकरार रखता है और क्लाइंट थ्रेड के लिए किसी अतिरिक्त प्रतीक्षा समय का परिचय नहीं देता है। यह केवल NSManagedObjectContextDidSaveNotificationनोटिफिकेशन हैंडलर में सर्वर के लिए संबंधित अनुरोधों को जारी करता है और फिर जारी करता है। लेकिन इस तरह से -save:कॉल हमेशा सफलतापूर्वक पूरा और ग्राहक कोड (अच्छी तरह से, यह देखते हुए कोर डाटा सहेजे गए परिवर्तनों के साथ ठीक है) वास्तव में कहा जाता है कि यह कोई रास्ता नहीं में विफल रहा है हो सकता है क्योंकि कुछ बचाने के सर्वर से प्रचार करने के लिए पता करने के लिए है 404या 421या जो कुछ भी सर्वर-साइड त्रुटि हुई। और इससे भी अधिक, स्थानीय भंडारण डेटा को अद्यतन करने के लिए हो जाता है, लेकिन सर्वर कभी भी परिवर्तनों के बारे में नहीं जानता है। असफल।

इसलिए, मैं इन सभी समस्याओं से निपटने के लिए एक संभावित समाधान / सामान्य प्रथाओं की तलाश कर रहा हूं:

  1. मैं नहीं चाहता कि कॉलिंग थ्रेड प्रत्येक -save:कॉल पर ब्लॉक करें जबकि नेटवर्क अनुरोध होता है।
  2. मैं यूआई में किसी तरह सूचनाएं प्राप्त करना चाहता हूं कि कुछ सिंक ऑपरेशन गलत हो गया।
  3. मैं चाहता हूं कि वास्तविक कोर डेटा सेव फेल होने के साथ ही सर्वर रिक्वेस्ट फेल हो जाए।

कोई विचार?


1
वाह, आपको पता नहीं है कि आपने यह सवाल पूछकर मुझे कितना परेशान किया है। जब भी मैं कॉल करता हूं, तो उपयोगकर्ता को डेटा के लिए प्रतीक्षा करने के लिए मैंने वर्तमान में अपना ऐप लागू कर दिया है (यद्यपि एक .NET वेबबेस सेवा के लिए)। मैं इसे अतुल्यकालिक बनाने के तरीके के बारे में सोच रहा हूं लेकिन यह पता नहीं लगा सका कि कैसे। आपके द्वारा प्रदान किए गए सभी संसाधनों के लिए धन्यवाद!
तेजस्वी येरुकलापुड़ी

बहुत बढ़िया सवाल, धन्यवाद।
जस्टिन

कोर रिसोर्स का लिंक टूटा हुआ है, क्या किसी को पता है कि इसे अभी कहां होस्ट किया गया है?

कोर रिसोर्स अभी भी GitHub पर होस्ट किया गया है: github.com/mikelaurence/CoreResource
eploko

और मूल साइट gitHub पर भी देखी जा सकती है: github.com/mikelaurence/coreresource.org
eploko

जवाबों:


26

आपको वास्तव में इस उपयोग के मामले में RestKit ( http://restkit.org ) पर एक नज़र डालनी चाहिए । इसे मॉडलिंग और दूरस्थ JSON संसाधनों को स्थानीय कोर डेटा समर्थित कैश में सिंक करने की समस्याओं को हल करने के लिए डिज़ाइन किया गया है। यह कैश से पूरी तरह से काम करने के लिए एक ऑफ़लाइन मोड का समर्थन करता है जब कोई नेटवर्क उपलब्ध नहीं होता है। सभी सिंकिंग एक बैकग्राउंड थ्रेड (नेटवर्क एक्सेस, पेलोड पार्सिंग और मैनेज ऑब्जेक्ट ऑब्जेक्ट मर्जिंग) पर होती है और डेलिगेट विधियों का एक समृद्ध सेट है ताकि आप बता सकें कि क्या चल रहा है।


18

तीन बुनियादी घटक हैं:

  1. UI क्रिया और कोरडाटा में परिवर्तन को जारी रखना
  2. सर्वर से परिवर्तित करना जारी रखना
  3. सर्वर की प्रतिक्रिया के साथ UI को ताज़ा करना

एक NSOperation + NSOperationQueue नेटवर्क अनुरोधों को व्यवस्थित रखने में मदद करेगा। एक प्रतिनिधि प्रोटोकॉल आपके यूआई वर्गों को समझने में मदद करेगा कि नेटवर्क अनुरोध किस स्थिति में हैं, कुछ इस तरह हैं:

@protocol NetworkOperationDelegate
  - (void)operation:(NSOperation *)op willSendRequest:(NSURLRequest *)request forChangedEntityWithId:(NSManagedObjectID *)entity;
  - (void)operation:(NSOperation *)op didSuccessfullySendRequest:(NSURLRequest *)request forChangedEntityWithId:(NSManagedObjectID *)entity;
  - (void)operation:(NSOperation *)op encounteredAnError:(NSError *)error afterSendingRequest:(NSURLRequest *)request forChangedEntityWithId:(NSManagedObjectID *)entity;
@end

निश्चित रूप से प्रोटोकॉल प्रारूप आपके विशिष्ट उपयोग के मामले पर निर्भर करेगा लेकिन अनिवार्य रूप से आप जो भी बना रहे हैं वह एक ऐसा तंत्र है जिसके द्वारा परिवर्तनों को आपके सर्वर तक "धक्का" दिया जा सकता है।

इसके बाद यूआई लूप पर विचार करने के लिए, अपने कोड को साफ रखने के लिए सेव को कॉल करना अच्छा होगा: और उन परिवर्तनों को स्वचालित रूप से सर्वर पर धकेल दिया जाए। आप इसके लिए NSManagedObjectContextDidSave नोटिफिकेशन का उपयोग कर सकते हैं।

- (void)managedObjectContextDidSave:(NSNotification *)saveNotification {
  NSArray *inserted = [[saveNotification userInfo] valueForKey:NSInsertedObjects];
  for (NSManagedObject *obj in inserted) {
    //create a new NSOperation for this entity which will invoke the appropraite rest api
    //add to operation queue
  }

  //do the same thing for deleted and updated objects
}

नेटवर्क संचालन सम्मिलित करने के लिए कम्प्यूटेशनल ओवरहेड कम होना चाहिए, हालांकि अगर यह यूआई पर ध्यान देने योग्य अंतराल बनाता है तो आप बस यूनिट आईडी को नोटिफिकेशन से बचा सकते हैं और बैकग्राउंड थ्रेड पर ऑपरेशन बना सकते हैं।

यदि आपका REST API बैचिंग का समर्थन करता है, तो आप पूरे सरणी को एक बार में भेज सकते हैं और फिर आपको यूआई को सूचित कर सकते हैं कि कई इकाइयां सिंक्रनाइज़ की गई थीं।

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


2

यह एक सिंक समस्या बन जाती है और इसे हल करना आसान नहीं होता है। यहाँ मैं क्या करूँगा: अपने iPhone UI में एक संदर्भ का उपयोग करें और फिर दूसरे संदर्भ (और एक अन्य थ्रेड) का उपयोग करके अपनी वेब सेवा से डेटा डाउनलोड करें। एक बार जब यह सब कुछ हो जाता है तो नीचे दी गई सिंक / आयात प्रक्रियाओं से गुजरें और सब कुछ ठीक से आयात होने के बाद अपने यूआई को रिफ्रेश करें। यदि नेटवर्क एक्सेस करते समय चीजें खराब हो जाती हैं, तो बस गैर-यूआई संदर्भ में परिवर्तन वापस करें। यह काम का एक गुच्छा है, लेकिन मुझे लगता है कि यह सबसे अच्छा तरीका है।

कोर डेटा: कुशलता से डेटा आयात करना

कोर डेटा: प्रबंधन बदलें

कोर डेटा: कोर डेटा के साथ मल्टी-थ्रेडिंग


0

आपको एक कॉलबैक फ़ंक्शन की आवश्यकता है जो दूसरे थ्रेड पर चलने वाला है (जहां वास्तविक सर्वर इंटरैक्शन होता है) और फिर परिणाम कोड / त्रुटि जानकारी को एक अर्ध-वैश्विक डेटा डाल दिया जाता है जिसे समय-समय पर यूआई थ्रेड द्वारा जांचा जाएगा। सुनिश्चित करें कि ध्वज के रूप में कार्य करने वाली संख्या की छेड़छाड़ परमाणु है या आप एक दौड़ की स्थिति के लिए जा रहे हैं - कहते हैं कि यदि आपकी त्रुटि प्रतिक्रिया 32 बाइट्स है, तो आपको एक int की आवश्यकता है (whihc में atomic acces) होना चाहिए और फिर आप इसे बरकरार रखेंगे। जब तक आपका बड़ा डेटा ब्लॉक नहीं लिखा जाता है, तब तक ऑफ / गलत / नॉट-रेडी अवस्था में और तब बोलने के लिए स्विच को फ्लिप करने के लिए "सही" लिखें।

क्लाइंट की ओर से सहसंबद्ध बचत के लिए आपको या तो बस उस डेटा को रखना होगा और उसे तब तक नहीं सहेजना होगा जब तक कि आपको यह सुनिश्चित करने के सर्वर से ओके न मिल जाए कि आपके पास रोलबैक विकल्प का एक किन्नफ है - कहते हैं कि डिलीट करने का एक तरीका सर्वर विफल है।

खबरदार कि यह कभी भी 100% सुरक्षित नहीं होगा जब तक कि आप पूरी तरह से 2-चरण प्रतिबद्ध प्रक्रिया नहीं करते हैं (क्लाइंट सेव या डिलीट सर्वर सर्वर से सिग्नल के बाद विफल हो सकता है) लेकिन यह बहुत कम से कम सर्वर पर आपको 2 ट्रिप खर्च करने जा रहा है ( अगर आपके एकमात्र रोलबैक विकल्प को हटा दिया जाए) तो आपकी कीमत 4 हो सकती है)।

आदर्श रूप से, आप ऑपरेशन के पूरे ब्लॉकिंग संस्करण को एक अलग थ्रेड पर करेंगे लेकिन आपको इसके लिए 4.0 की आवश्यकता होगी।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.