अस्थाई NSManagedObject उदाहरणों से कैसे निपटें?


86

मुझे NSManagedObjectउदाहरण बनाने की जरूरत है , उनके साथ कुछ सामान करें और फिर उन्हें कचरा दें या स्क्वैलाइट डीबी को स्टोर करें। समस्या यह है कि, मैं NSManagedObjectअसंबद्ध के उदाहरण नहीं बना सकता NSManagedObjectContextऔर इसका मतलब है कि मुझे किसी भी तरह से यह तय करने के बाद स्पष्ट करना होगा कि मुझे अपने डीबी में कुछ वस्तुओं की आवश्यकता नहीं है।

इससे निपटने के लिए, मैंने एक ही समन्वयक का उपयोग करके इन-मेमोरी स्टोर बनाया है और मैं अभी उपयोग करके अस्थाई वस्तुएं रख रहा हूं assignObject:toPersistentStore., मैं यह कैसे सुनिश्चित करूं कि ये अस्थायी वस्तुएं डेटा को प्राप्त न करें, जिसे मैं प्राप्त करता हूं दोनों दुकानों के संदर्भ में आम? या मुझे ऐसे कार्य के लिए अलग संदर्भ बनाने होंगे?


युपीडी:

अब मैं इन-मेमोरी स्टोर के लिए अलग संदर्भ बनाने के बारे में सोच रहा हूं। मैं वस्तुओं को एक संदर्भ से दूसरे में कैसे स्थानांतरित करूं? बस [संदर्भ सम्मिलित करें का उपयोग करें:]? क्या यह इस सेटअप में ठीक काम करेगा? यदि मैं वस्तुओं के ग्राफ से एक वस्तु सम्मिलित करता हूं, तो क्या पूरा ग्राफ भी संदर्भ में डाला जाता है?


यह एक अलग प्रश्न होना चाहिए क्योंकि आपने इसे उत्तर दिया है। कोई नया प्रश्न बनाएं और समझाने क्यों आप तो आपको एक अलग पूरे कोर डाटा ढेर की जरूरत महसूस हो रहा है सिर्फ एक में स्मृति की दुकान के लिए। मुझे आपके साथ प्रश्न का पता लगाने में खुशी होगी।
मार्कस एस। ज़रा

UPD सेक्शन अब प्रासंगिक नहीं है, क्योंकि मैंने एक और तरीका चुना है, अपने जवाब के लिए मेरी आखिरी टिप्पणी देखें।
fspirit

जवाबों:


146

नोट: यह उत्तर बहुत पुराना है। पूर्ण इतिहास के लिए टिप्पणियाँ देखें। मेरी सिफारिश तब से बदल गई है और मैं अब बिना पढ़े NSManagedObjectउदाहरणों का उपयोग करने की सलाह नहीं देता । मेरी वर्तमान सिफारिश अस्थायी बाल NSManagedObjectContextउदाहरणों का उपयोग करने की है ।

मूल उत्तर

ऐसा करने का सबसे आसान तरीका है NSManagedObjectबिना किसी संबद्ध के अपने उदाहरणों का निर्माण करना NSManagedObjectContext

NSEntityDescription *entity = [NSEntityDescription entityForName:@"MyEntity" inManagedObjectContext:myMOC];
NSManagedObject *unassociatedObject = [[NSManagedObject alloc] initWithEntity:entity insertIntoManagedObjectContext:nil];

फिर जब आप इसे सहेजना चाहते हैं:

[myMOC insertObject:unassociatedObject];
NSError *error = nil;
if (![myMoc save:&error]) {
  //Respond to the error
}

6
अगर unassociatedObject अन्य unassociated ऑब्जेक्ट के लिए refs है, तो क्या मुझे उन्हें एक-एक करके सम्मिलित करना चाहिए या myMOC सभी Ref को इकट्ठा करने और उन्हें भी सम्मिलित करने के लिए पर्याप्त स्मार्ट है?
fspirit

6
यह रिश्तों को संभालने के लिए काफी स्मार्ट है।
मार्कस एस। ज़रा

2
मुझे पसंद है कि इस दृष्टिकोण से आप नियमित रूप से डेटा ऑब्जेक्ट्स की तरह एमओ का इलाज कर सकते हैं, इससे पहले कि आप उन्हें स्टोर करने का फैसला करें, लेकिन कोरडाटा अनुबंध द्वारा "समर्थित" कैसे और इसलिए यह भविष्य में कैसे होता है, इसके बारे में चिंतित हैं। क्या सेब कहीं भी इस दृष्टिकोण का उल्लेख या उपयोग करता है? क्योंकि यदि नहीं, तो भविष्य में iOS रिलीज MOC पर निर्भर रहने और इस दृष्टिकोण को तोड़ने के लिए गतिशील गुणों को बदल सकता है। इस पर ऐप्पल डॉक्स स्पष्ट नहीं हैं: वे संदर्भ के महत्व और नामित इनिशियलाइज़र पर जोर देते हैं, लेकिन एमओ डॉक्टर में एक उल्लेख है "यदि संदर्भ शून्य नहीं है, तो ..." यह सुझाव देते हुए कि शून्य ठीक हो सकता है
एक प्रकार का फल

41
मैंने कुछ समय पहले इस दृष्टिकोण का उपयोग किया था लेकिन अजीब व्यवहार और दुर्घटनाओं को देखना शुरू कर दिया जब मैंने उन वस्तुओं को संशोधित किया और / या एमओसी में डालने से पहले उनके लिए संबंध बनाए। मैंने डब्ल्यूडब्ल्यूडीसी में एक कोर डेटा इंजीनियर के माध्यम से यह बात कही और उन्होंने कहा कि जब तक बिना लाइसेंस वाली वस्तुओं के लिए एपीआई है, उन्होंने एमओसी के रूप में इसका उपयोग करने के खिलाफ जोरदार सिफारिश की, जो कि अपनी वस्तुओं द्वारा भेजे गए केवीओ सूचनाओं पर बहुत निर्भर करता है। उन्होंने अस्थायी वस्तुओं के लिए नियमित रूप से NSObject का उपयोग करने का सुझाव दिया, क्योंकि यह बहुत सुरक्षित है।
एड्रियन शॉनिग

7
यह iOS 8 के साथ अच्छी तरह से काम नहीं करता है, खासकर रिश्तों को बनाए रखने के साथ। क्या कोई और इसकी पुष्टि कर सकता है?
जनुम त्रिवेदी

40

iOS5 माइक वेलर के उत्तर के लिए एक सरल विकल्प प्रदान करता है। इसके बजाय एक बच्चे का उपयोग करें NSManagedObjectContext। यह NSNotificationCenter के माध्यम से trampoline की आवश्यकता को हटाता है

बाल संदर्भ बनाने के लिए:

NSManagedObjectContext *childContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType];
childContext.parentContext = myMangedObjectContext;

फिर बच्चे के संदर्भ का उपयोग करके अपनी वस्तुओं का निर्माण करें:

NSManagedObject *o = [NSEntityDescription insertNewObjectForEntityForName:@"MyObject" inManagedObjectContext:childContext];

परिवर्तन केवल तभी लागू होते हैं जब बच्चा संदर्भ सहेजा जाता है। इसलिए परिवर्तनों को त्यागने के लिए सिर्फ बचत न करें।

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

NSManagedObjectID *mid = [myManagedObject objectID];
MyManagedObject *mySafeManagedObject = [childContext objectWithID:mid];
object.relationship=mySafeManagedObject;

ध्यान दें, बच्चे के संदर्भ को सहेजना माता-पिता के संदर्भ में परिवर्तन लागू करता है। मूल संदर्भ को सहेजना परिवर्तनों को बनाए रखता है।

पूर्ण विवरण के लिए wwdc 2012 सत्र 214 देखें ।


1
यह सुझाव देने के लिए धन्यवाद! मैंने एक डेमो संदर्भ का उपयोग करते हुए इस विधि का परीक्षण किया है, जैसे कि nil संदर्भ का उपयोग करना और कम से कम OSX पर, यह काम करते समय एक nil संदर्भ डालने पर बचत करते समय अपने गुणों को खो दिया - github.com/seltzered/CoreDataMagicalRecordadempObjectsDemo
Vivek Gani

mocतीसरे स्निपेट में कौन सा है ? यह है childContextया myMangedObjectContext?
बुगलाफ

यह चाइल्ड कॉन्टेक्स्ट है
रेलवेपरेड

यह समाधान नील संदर्भ होने से बेहतर है।
विल वाई

चूंकि NSManagedObjectपहले से ही प्रासंगिक प्रदान करता है NSManagedObjectContext, आप संदर्भ की पसंद को स्वचालित कर सकते हैं: NSManagedObject* objectRelatedContextually = [objectWithRelationship.managedObjectContext objectWithID:objectRelated.objectID];और फिर objectWithRelationship.relationship = objectRelatedContextually;
गैरी

9

इस तरह की चीज़ को प्राप्त करने का सही तरीका एक नए प्रबंधित ऑब्जेक्ट संदर्भ के साथ है। आप एक ही स्थिर स्टोर के साथ एक प्रबंधित ऑब्जेक्ट संदर्भ बनाते हैं:

NSManagedObjectContext *tempContext = [[[NSManagedObjectContext alloc] init] autorelease];
[tempContext setPersistentStore:[originalContext persistentStore]];

फिर आप नई वस्तुओं को जोड़ते हैं, उन्हें म्यूट करते हैं, आदि।

जब सहेजने का समय आता है, तो आपको tempContext पर [tempContext save: ...] को कॉल करने की आवश्यकता होती है, और उस मूल संदर्भ में मर्ज करने के लिए सेव नोटिफिकेशन को हैंडल करें। वस्तुओं को छोड़ने के लिए, बस इस अस्थायी संदर्भ को जारी करें और इसके बारे में भूल जाएं।

इसलिए जब आप अस्थायी संदर्भ को सहेजते हैं, तो परिवर्तन स्टोर पर बने रहते हैं, और आपको केवल उन परिवर्तनों को अपने मुख्य संदर्भ में वापस लाने की आवश्यकता होती है:

/* Called when the temp context is saved */
- (void)tempContextSaved:(NSNotification *)notification {
    /* Merge the changes into the original managed object context */
    [originalContext mergeChangesFromContextDidSaveNotification:notification];
}

// Here's where we do the save itself

// Add the notification handler
[[NSNotificationCenter defaultCenter] addObserver:self
                                         selector:@selector(tempContextSaved:)
                                             name:NSManagedObjectContextDidSaveNotification
                                           object:tempContext];

// Save
[tempContext save:NULL];
// Remove the handler again
[[NSNotificationCenter defaultCenter] removeObserver:self
                                                name:NSManagedObjectContextDidSaveNotification
                                              object:tempContext];

यह वह तरीका भी है जिसे आपको बहु-थ्रेडेड कोर डेटा संचालन को संभालना चाहिए। प्रति सूत्र एक प्रसंग।

यदि आपको इस अस्थायी संदर्भ (संबंध आदि जोड़ने के लिए) से मौजूदा वस्तुओं का उपयोग करने की आवश्यकता है, तो आपको इसके लिए एक नया उदाहरण प्राप्त करने के लिए ऑब्जेक्ट की आईडी का उपयोग करने की आवश्यकता है:

NSManagedObject *objectInOriginalContext = ...;
NSManagedObject *objectInTemporaryContext = [tempContext objectWithID:[objectInOriginalContext objectID]];

यदि आप NSManagedObjectगलत संदर्भ में उपयोग करने का प्रयास करते हैं तो आपको बचत करते समय अपवाद मिलेंगे।


इसके लिए दूसरा संदर्भ बनाना बहुत ही बेकार है क्योंकि NSManagedObjectContextमेमोरी और सीपीयू दोनों में ही यह महंगा है। मुझे लगता है कि यह मूल रूप से Apple के कुछ उदाहरणों में था, लेकिन उन्होंने उन उदाहरणों को अपडेट और सही किया है।
मार्कस एस। ज़रा

2
CoreDataBooks उदाहरण कोड के लिए Apple अभी भी इस तकनीक (दूसरा प्रबंधित ऑब्जेक्ट संदर्भ बना रहा है) का उपयोग कर रहा है।
नीवन राजा

1
नोट Apple ने CoreDataBooks को अपडेट किया है, वास्तव में यह अभी भी दो संदर्भों का उपयोग करता है, लेकिन अब दूसरा संदर्भ पहले का बच्चा है। WWDC 2011 की प्रस्तुति 303 (iOS में कोर डेटा में नया क्या है) में इस तकनीक पर चर्चा (और अनुशंसित) की गई है और यहाँ उल्लेख किया गया है (बहुत, MUCH, ऊपर की ओर विलय के लिए सरल कोड) stackoverflow.com/questions/9331469/…
ररबबार

4
"इसके लिए सिर्फ एक दूसरा संदर्भ बनाना बहुत ही बेकार है क्योंकि NSManagedObjectContext मेमोरी और सीपीयू दोनों में महंगा है।" । नहीं यह नहीं। लगातार स्टोर समन्वयक की निर्भरताएं (प्रबंधित ऑब्जेक्ट मॉडल और कंक्रीट स्टोर) संदर्भ नहीं हैं। प्रसंग हल्के होते हैं।
quellish

3
@ एक्सेलिश सहमत Apple ने WWDC में अपनी हालिया कोर डेटा प्रदर्शन वार्ता में कहा है कि संदर्भ बनाना बहुत हल्का है।
जेसी

9

शून्य संदर्भ से अस्थायी ऑब्जेक्ट बनाना तब तक ठीक काम करता है जब तक कि आप वास्तव में किसी वस्तु के साथ संबंध बनाने की कोशिश नहीं करते हैं! = Nil!

सुनिश्चित करें कि आपके साथ ठीक है।


मैं इसके साथ ठीक नहीं हूँ
चार्ली

8

आप जो वर्णन कर रहे हैं वह वास्तव में क्या है NSManagedObjectContext है।

से कोर डेटा की बुनियादी जानकारी: कोर डाटा प्रोग्रामिंग गाइड

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

और कोर डेटा प्रोग्रामिंग गाइड: प्रबंधित ऑब्जेक्ट सत्यापन

यह एक "स्क्रैच पैड" का प्रतिनिधित्व करने वाले एक प्रबंधित ऑब्जेक्ट संदर्भ के विचार को भी रेखांकित करता है — सामान्य तौर पर आप स्क्रैच पैड पर प्रबंधित ऑब्जेक्ट ला सकते हैं और उन्हें संपादित कर सकते हैं, हालांकि आप अंततः परिवर्तनों को पूरा करने से पहले या उन्हें छोड़ना चाहते हैं।

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

एक संदर्भ बनाएं, उस संदर्भ में प्रबंधित ऑब्जेक्ट बनाएं और संशोधित करें। यदि आप उन्हें जारी रखना चाहते हैं और उन परिवर्तनों को संप्रेषित करना चाहते हैं, तो संदर्भ को बचाएं। अन्यथा इसे त्याग दें।

एक NSManagedObjectContextसे स्वतंत्र प्रबंधित वस्तुओं को बनाने का प्रयास मुसीबत के लिए पूछ रहा है। याद रखें कि कोर डेटा अंततः एक वस्तु ग्राफ के लिए एक परिवर्तन ट्रैकिंग तंत्र है। इस वजह से, प्रबंधित ऑब्जेक्ट वास्तव में प्रबंधित ऑब्जेक्ट संदर्भ का हिस्सा हैं । संदर्भ उनके जीवन चक्र को देखता है , और संदर्भ के बिना प्रबंधित वस्तु कार्यक्षमता के सभी सही ढंग से काम नहीं करेंगे।


6

अस्थायी ऑब्जेक्ट के आपके उपयोग के आधार पर उपरोक्त सिफारिशों के लिए कुछ चेतावनी हैं। मेरा उपयोग मामला यह है कि मैं एक अस्थायी वस्तु बनाना चाहता हूं और इसे विचारों पर बांधता हूं। जब उपयोगकर्ता इस ऑब्जेक्ट को सहेजने का विरोध करता है, तो मैं मौजूदा ऑब्जेक्ट (ओं) के लिए संबंधों को सेटअप करना चाहता हूं और सहेजें। मैं उन मूल्यों को धारण करने के लिए एक अस्थायी वस्तु बनाने से बचने के लिए ऐसा करना चाहता हूं। (हां, मैं तब तक इंतजार कर सकता था जब तक उपयोगकर्ता बचाता है और फिर दृश्य सामग्री को पकड़ लेता है लेकिन मैं इन विचारों को एक तालिका के अंदर रख रहा हूं और ऐसा करने का तर्क कम सुरुचिपूर्ण है।)

अस्थायी वस्तुओं के लिए विकल्प हैं:

1) (पसंदीदा) एक बच्चे के संदर्भ में अस्थायी वस्तु बनाएं। यह काम नहीं करेगा क्योंकि मैं यूआई को ऑब्जेक्ट को बाइंड कर रहा हूं और मैं इस बात की गारंटी नहीं दे सकता कि ऑब्जेक्ट एक्सेसर्स को चाइल्ड के संदर्भ में कहा जाता है। (मुझे कोई दस्तावेज नहीं मिला है जो कहता है कि अन्यथा मुझे ऐसा करना है।)

2) अस्थायी ऑब्जेक्ट को नील ऑब्जेक्ट संदर्भ के साथ बनाएं। यह काम नहीं करता है और डेटा हानि / भ्रष्टाचार के परिणामस्वरूप होता है।

मेरा समाधान: मैंने इसे अस्थायी ऑब्जेक्ट को नील ऑब्जेक्ट संदर्भ के साथ बनाकर हल किया है, लेकिन जब मैं ऑब्जेक्ट को सेव करता हूं, तो इसे # 2 के रूप में सम्मिलित करने के बजाय, मैं इसकी सभी विशेषताओं को एक नए ऑब्जेक्ट में कॉपी करता हूं जिसे मैं मुख्य संदर्भ में बनाता हूं। मैंने अपने NSManagedObject उपवर्ग में एक सहायक विधि बनाई, जिसे cloneInto कहा जाता है: जो मुझे किसी भी ऑब्जेक्ट पर आसानी से विशेषताओं और संबंधों की प्रतिलिपि बनाने देता है।


यही मैं ढूंढ रहा हूं। लेकिन मेरी शंका यह है कि आप संबंध विशेषताओं को कैसे संभालेंगे?
मणि

1

मेरे लिए माक्र्स का जवाब काम नहीं आया। यहाँ मेरे लिए क्या काम किया गया है:

NSEntityDescription entityForName:@"MyEntity" inManagedObjectContext:myMOC];
NSManagedObject *unassociatedObject = [[NSManagedObject alloc] initWithEntity:entity insertIntoManagedObjectContext:nil];

फिर, अगर मैं इसे बचाने का फैसला करता हूं:

[myMOC insertObject:unassociatedObjet];
NSError *error = nil;
[myMoc save:&error];
//Check the error!

हमें इसे रिलीज करना भी नहीं भूलना चाहिए

[unassociatedObject release]

1

मैं इस जवाब को फिर से लिख रहा हूं स्विफ्ट के लिए को क्योंकि प्रश्न के लिए स्विफ्ट पुनर्निर्देशित सभी समान प्रश्न हैं।

आप निम्न कोड का उपयोग करके किसी भी ManagedContext के बिना ऑब्जेक्ट की घोषणा कर सकते हैं।

let entity = NSEntityDescription.entity(forEntityName: "EntityName", in: myContext)
let unassociatedObject = NSManagedObject.init(entity: entity!, insertInto: nil)

बाद में, ऑब्जेक्ट को बचाने के लिए आप इसे संदर्भ में सम्मिलित कर सकते हैं और इसे सहेज सकते हैं।

myContext.insert(unassociatedObject)
// Saving the object
do {
    try self.stack.saveContext()
    } catch {
        print("save unsuccessful")
    }
}
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.