2013-03-12 7 views
10

का उपयोग कर मैं एक समस्या यह है कि जब कोर डाटा में नेस्टेड प्रबंधित ऑब्जेक्ट संदर्भ का उपयोग कर उठता है करने के लिए एक सभ्य समाधान यह पता लगाने के लिए संघर्ष कर रहा हूँ। एक मॉडल लें जिसमें दो एनसाइट्स, व्यक्ति और नाम हों, जहां प्रत्येक व्यक्ति के नाम के साथ एक-से-एक संबंध होता है, और नाम का व्यक्ति संबंध वैकल्पिक नहीं होता है। इससे पहले, व्यक्ति की -awakeFromInsert विधि में, मैं स्वचालित रूप से एक का नाम इकाई नए व्यक्ति के लिए बनाना होगा:कैसे सेटअप कोर डाटा रिश्ते को जब नेस्टेड संदर्भों

- (void)awakeFromInsert 
{ 
    [super awakeFromInsert]; 

    NSManagedObjectContext *context = [self managedObjectContext]; 
    self.name = [NSEntityDescription insertNewObjectForEntityForName:@"Name" inManagedObjectContext:context]; 
} 

यह एक एकल, गैर नेस्टेड प्रबंधित वस्तु के संदर्भ में ठीक काम करता है। लेकिन अगर संदर्भ एक माता पिता के संदर्भ है, जब बच्चे संदर्भ सहेजा जाता है, एक नया व्यक्ति वस्तु माता पिता संदर्भ में बनाई गई है, और -awakeFromInsert इस नई वस्तु पर फिर से कहा जाता है मूल व्यक्ति के गुणों और संबंधों पर कॉपी कर रहे हैं इससे पहले कि। इसलिए, एक और नाम ऑब्जेक्ट बनाया गया है, फिर मौजूदा नाम संबंधों की प्रतिलिपि बनाते समय "डिस्कनेक्ट" हो जाता है। बचत विफल हो जाती है क्योंकि फ़्लोटिंग नाम की अब-शून्य person संबंध की विफलता विफल हो जाती है। इस समस्या को here के साथ-साथ अन्य स्थानों में वर्णित किया गया है।

अब तक, मैं इस समस्या का एक अच्छा समाधान के साथ आ नहीं कर पाए थे। Lazily गेटर विधि में संबंध बनाने वास्तव में क्योंकि गेटर आंतरिक कोर डाटा मशीनरी द्वारा कहा जाता है, जब नए व्यक्ति माता पिता संदर्भ में बनाया जाता है, एक ही समस्या का कारण बनता है।

एकमात्र चीज जिसके साथ मैं आ सकता हूं, स्वचालित रिलेशनशिप पीढ़ी से गुजरना है, और हमेशा व्यक्ति को बनाता है जो नियंत्रक वर्ग में बनाता है जो व्यक्ति बनाता है, या सुविधा विधि (उदाहरण के लिए +[Person insertNewPersonInManagedObjectContext:]) जिसे केवल मेरे द्वारा बुलाया जाता है कोड, और हमेशा एक नया व्यक्ति वस्तु को स्पष्ट रूप से बनाने के लिए इस्तेमाल विधि है। शायद यह सबसे अच्छा समाधान है, लेकिन मैं प्रबंधित वस्तुओं को बनाने के लिए केवल एक विधि का उपयोग करने की अनुमति देने के बारे में इतना सख्त नहीं होना चाहूंगा, जब अन्य सृजन विधियों पर मेरा कोई नियंत्रण नहीं है और जिसका उपयोग मैं नहीं कर सकता आसानी से जांचें/बहिष्कृत करें, मौजूद हैं। एक बात के लिए, इसका अर्थ यह होगा कि वे प्रबंधित ऑब्जेक्ट्स बनाने के तरीके को अनुकूलित करने के लिए एकाधिक एनएसएआरएआर कंट्रोलर उप-वर्गों का अर्थ लेंगे।

क्या किसी और को इस समस्या का सामना करना पड़ा है जो एक सुरुचिपूर्ण समाधान के साथ आता है जो एक एनएसएमएनेज ऑब्जेक्ट को सृजन/सम्मिलन पर स्वचालित रूप से रिलेशनशिप ऑब्जेक्ट बनाने की अनुमति देता है?

+0

के रिश्ते वैकल्पिक जा करने के लिए मान लेते हैं। फिर आप एक अनाथ नाम वस्तु के साथ समाप्त होंगे, साथ ही उनके संबंधित संदर्भ में दो "उचित" नाम ऑब्जेक्ट्स का अंत करेंगे। यह दिलचस्प होगा: 1. यह पता लगाएं कि "उचित" ऑब्जेक्ट आईडी समान हैं (वे बाद में होने जा रहे हैं, लेकिन अभी के लिए वे अस्थायी हैं) और 2. यदि अनाथ नाम ऑब्जेक्ट की आईडी अलग है। यदि ऐसा है, तो आप नाम पर awakeFromInsert भी लागू कर सकते हैं, जिससे बच्चे के संदर्भ में भाई की जांच करनी पड़ती है और अगर इसे कोई नहीं मिलता है तो उसे हटा दिया जाता है। इसे सहेजने से पहले संदर्भ से हटा दिया जाएगा, और आशा है कि सत्यापन से पहले ... – Toastor

+0

हम्म मुझे लगता है कि मैं गलत हो सकता हूं - क्योंकि इस बिंदु पर अनाथ नाम बनाया जा रहा है, बच्चे का संदर्भ पहले ही सहेजा गया है, " उचित "नाम वस्तुएं * * मुझे इस पल के लिए अलग हो सकती हैं, क्योंकि एक नाम सहेजा गया है और दूसरा अभी भी अस्थायी है। फिर भी, यह जांच/कोशिश करने लायक हो सकता है ... – Toastor

उत्तर

1

मैं सुविधा विधि समाधान के साथ जा रहा हूं। मेरे ऐप में सभी NSManagedObject उप-वर्गों में +insertInManagedObjectContext: विधि है। उन वस्तुओं के उदाहरण बनाना (अपने कोड में) हमेशा उस विधि का उपयोग करके किया गया है। उस विधि के अंदर, मैं यह कर:

+ (instancetype)insertInManagedObjectContext:(NSManagedObjectContext *)moc 
{ 
    MyManagedObject *result = [NSEntityDescription insertNewObjectForEntityForName:@"MyEntityName" inManagedObjectContext:moc] 
    [result awakeFromCreation]; 
    return result; 
} 

- (void)awakeFromCreation 
{ 
    // Do here what used to be done in -awakeFromInsert. 
    // Set up default relationships, etc. 
} 

NSArrayController जारी करने के लिए के रूप में, को सुलझाने कि सभी बुरा नहीं है। मैं बस NSArrayController का एक उपवर्ग बनाया, -newObject overrode, और मेरे एप्लिकेशन में सभी प्रासंगिक NSArrayControllers के लिए कि उपवर्ग प्रयोग किया है:

@implementation ORSManagedObjectsArrayController 

- (id)newObject 
{ 
    NSManagedObjectContext *moc = [self managedObjectContext]; 
    NSEntityDescription *entity = [NSEntityDescription entityForName:[self entityName] 
               inManagedObjectContext:moc]; 
    if (!entity) return nil; 

    Class class = NSClassFromString([entity managedObjectClassName]); 
    return [class insertInManagedObjectContext:moc]; 
} 

@end 
1

पहला विचार जो मन में आता है, जबकि Name के person संबंध गैर वैकल्पिक है, आप यह नहीं कहा कि Person 'कि रों name संबंध भी गैर वैकल्पिक है। क्या Person कोई Name के साथ बनाना ठीक है, तो अपने कोड से निपटें, और उसके बाद Name को बाद में जब आपको वास्तव में आवश्यकता हो तो बनाएं?

यदि नहीं

, एक आसान तरीका एक Name बनाने से पहले जाँच करने के लिए है कि क्या आप जड़ संदर्भ पर हैं बस है:

- (void)awakeFromInsert 
{ 
    [super awakeFromInsert]; 

    NSManagedObjectContext *context = [self managedObjectContext]; 
    if ([context parentContext] != nil) { 
     self.name = [NSEntityDescription insertNewObjectForEntityForName:@"Name" inManagedObjectContext:context]; 
    } 
} 

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

इसके बजाय मैं जो संभवतः करता हूं वह insertNewPersonInManagedObjectContext: जैसा वर्णन करता है। फिर जहां उदाहरणों आप (अर्थात सरणी नियंत्रक) के लिए बनाई गई हो किसी भी मामले को संभालने के लिए निम्नलिखित की तरह कुछ के साथ यह पूरक:

- (void)willSave 
{ 
    if ([self name] == nil) { 
     NSManagedObjectContext *context = [self managedObjectContext]; 
     Name *name = [NSEntityDescription insertNewObjectForEntityForName:@"Name" inManagedObjectContext:context]; 
     [self setName:name]; 
    } 
} 

...और निश्चित रूप से एक कस्टम awakeFromInsert से परेशान न करें ...

+0

उत्तर टॉम के लिए धन्यवाद। मैंने निर्दिष्ट नहीं किया, लेकिन व्यक्ति का नाम संबंध वास्तव में गैर-वैकल्पिक है। (व्यक्ति/नाम एक उदाहरण है, मेरी वास्तविक संस्थाएं अलग हैं।) '-awakeFromInsert' में संदर्भ की जांच करना एक दिलचस्प विचार है। अभी के लिए, मेरे पास केवल 2 संदर्भ हैं, लेकिन एक अच्छा मौका है कि मैं तीसरे स्तर के संदर्भ, वर्तमान बच्चे के बाद में एक बच्चा चाहता हूं। मुझे लगता है कि आपका अंतिम सुझाव एक बहुत अच्छा है। लेकिन हकीकत में यूआई उम्मीद करता है कि प्रत्येक व्यक्ति पर नाम संबंध हो, क्योंकि 'नाम' संपादित करना ऐप की मुख्य चीजों में से एक है। शायद कस्टम सरणी नियंत्रक यह है ... –

+0

यह कारणों में से एक है कि मैं अभी भी नेस्टेड पैरेंट/बाल संदर्भों के लिए कई स्वतंत्र संदर्भों के पैटर्न को प्राथमिकता देता हूं। यदि यहां कोई अभिभावक/बाल संबंध नहीं था, तो आपके 'जागने के लिए प्रवेश' केवल एक बार बुलाया जाएगा, और 'मर्ज चेंजफ्रॉमकॉन्टेक्स्टडिडसेव नोटिफिकेशन' को कॉल करने के लिए कॉल: 'यह सुनिश्चित करेगा कि अन्य संदर्भों को नया डेटा मिले। यदि कस्टम सरणी नियंत्रक नहीं हैं, तो आपको किसी भी खतरनाक 'नाम' उदाहरणों को सहेजने, खोजने और निकालने से पहले कॉल करने के लिए एक क्लीनअप विधि जोड़ने की आवश्यकता हो सकती है। –

संबंधित मुद्दे