2012-06-07 10 views
16

मुझे दो अलग xcdatamodel फ़ाइलों द्वारा परिभाषित स्टोर से माइग्रेट करते समय हल्के माइग्रेशन करने में समस्या आ रही है।कोर डेटा - लाइटवेट माइग्रेशन और एकाधिक कोर डेटा मॉडल फाइलें (xcdatamodel)

मेरे ऐप के संस्करण 1.0 में, मॉडल मॉडल-ए में मॉडलिंग-ए और अन्य सभी चीज़ों में मॉडल को तोड़ दिया गया था। संकलन करते समय, मॉडल को एक साथ समूहीकृत किया जाएगा और सब कुछ सुचारू रूप से आगे बढ़ेगा।

नए संस्करण, 1.1 पर काम करते समय, मैंने मॉडल-बी में एक नया मॉडल संस्करण जोड़कर और उस नए संस्करण को सक्रिय के रूप में सेट करके मॉडल-बी को अपग्रेड किया।

समस्या तब उठती है जब 1.0 से 1.1 तक अपग्रेड हो जाती है। ऐसा लगता है कि कोर डेटा डिस्क पर मॉडल स्टोर (संस्करण 1.0 द्वारा बनाया गया) की जांच करता है और मॉडल का वर्णन करता है जो इसका वर्णन करता है लेकिन पूरे स्टोर को परिभाषित करने वाला एक एकल मॉडल ढूंढने में असमर्थ है (मॉडल-ए केवल कवर एनालिटिक्स, और मॉडल-बी कवर बाकी सब कुछ), इसलिए यह "स्रोत स्टोर के लिए मॉडल नहीं ढूंढ सकता" त्रुटि फेंकता है।

क्या किसी को मॉडल को अलग करने का समाधान मिला है, लेकिन अभी भी उन्नत माइग्रेशन को परिभाषित करने के अतिरिक्त परेशानी के बिना उन्नयन + हल्के माइग्रेशन को काम करने की इजाजत है?

NSArray *modelNames = [NSArray arrayWithObjects:@"model-A", @"model-B", nil]; 
    NSMutableArray *models = [NSMutableArray array]; 
    for (NSString *name in modelNames) 
    { 
     LogInfo(@"loading model %@", name); 
     NSURL *modelURL = [[NSBundle mainBundle] URLForResource:name withExtension:@"momd"]; 
     NSManagedObjectModel *model = [[[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL] autorelease]; 
     [models addObject:model]; 
    } 

    // combine all the separate models into one big one 
    objectModel = [[NSManagedObjectModel modelByMergingModels:models] retain]; 

    NSURL *documentsDirectory = [NSURL fileURLWithPath:[SuperFileManager documentsDirectory] isDirectory:YES]; 
    NSURL *storeURL = [documentsDirectory URLByAppendingPathComponent:@"database.sqlite"]; 
    NSError *error = nil; 

    coordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:objectModel]; 
    NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys: 
                [NSNumber numberWithBool:YES], NSMigratePersistentStoresAutomaticallyOption, 
                [NSNumber numberWithBool:YES], NSInferMappingModelAutomaticallyOption, 
                nil]; 

    if (![coordinator addPersistentStoreWithType:NSSQLiteStoreType 
            configuration:nil 
              URL:storeURL 
             options:options 
              error:&error]) 
    { 
     NSLog(@"Unresolved error %@, %@", error, [error userInfo]); 
     abort(); 
    } 

उत्तर

8

डब्ल्यूडब्ल्यूडीसी 2012 प्रयोगशाला में भाग लेने और कोर डेटा टीम के साथ बैठक करने के बाद, ऐसा लगता है कि आपको अपनी सभी मॉडल जानकारी को एक xcdatamodel में डालने के लिए मजबूर होना पड़ता है। CoreData अपने मौजूदा स्टोर्स को स्टोर करने वाले स्टोर्स के संयोजन के रूप में जांचने के लिए बुद्धिमान नहीं है और अभी भी डिस्क पर है। चूंकि सी। रोल्ड ने बताया, आप पुराने xcdatamodel फ़ाइलों पर कुछ प्रसंस्करण कर सकते हैं, लेकिन यह काफी दुखी है कि कोर डेटा इसे और अधिक सुंदर तरीके से संभाल नहीं करता है।

+0

इस पर कोई अपडेट? – codepushr

+0

@ कोडिंग्रोग - दुर्भाग्य से नहीं। टीम जिस समय मैं कोर डेटा का उपयोग करके त्याग कर रहा था और मैंने एंड्रॉइड प्रोग्रामिंग पर स्विच किया था। माफ़ कीजिये। :/ – Mark

0

अपने कोर डाटा मॉडल के उन्नयन के लिए सबसे अच्छा तरीका है एक संस्करण को जोड़ने के लिए है:

यहाँ मॉडल लोड करने के लिए इस्तेमाल किया कोड का स्निपेट है। यदि आप ऐसा नहीं करते हैं, तो आप क्रैश, खतरे अद्यतन और उस तरह की चीजों में नष्ट हो जाएंगे।

एक नया संस्करण जोड़ना वास्तव में काफी आसान है। आप डेटामैडेल फ़ाइल का चयन करते हैं और 'संपादक> मॉडल संस्करण जोड़ें' का चयन करते हैं। यह आपको पिछले मॉडल के आधार पर एक नया डेटाबेस संस्करण जोड़ने में सक्षम करेगा। इसके बाद आपको नवीनतम डेटामैडल को नवीनतम पर सेट करने की आवश्यकता है: http://cl.ly/2h1g301b0N143t0b1k2K

आईओएस एक नया संस्करण स्थापित होने पर डेटा स्वचालित रूप से (मेरे मामले में) माइग्रेट करेगा।

उम्मीद है कि इससे मदद मिलती है।

+3

यह ठीक काम करता है आप एक ही xcdatamodel है जब। यदि आपके पास एकाधिक हैं और आप उनमें से एक को अपग्रेड करते हैं, तो कोर डेटा चीजों को मेल नहीं कर सकता है। डब्ल्यूडब्ल्यूडीसी 2012 प्रयोगशाला में भाग लेने के बाद, ऐसा लगता है कि आपको मूल रूप से एक ही xcdatamodel में अपनी सभी मॉडल जानकारी डालने के लिए मजबूर होना पड़ता है और जैसा कि आप सुझाव देते हैं! – Mark

8

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

मेरा मानना ​​है कि इस समस्या को हल करने के लिए सबसे आसान तरीका है:

  1. पिक जो मॉडल आप रख रहे हैं - कहते हैं कि ModelB - और प्रकाशित संस्करण के आधार पर इसके लिए एक नया संस्करण बनाने के। मैं प्रकाशित संस्करण ModelBv1 और नया संस्करण ModelBv1_merge कहूंगा।

  2. टेक्स्ट एडिटर (यानी ModelA.xcdatamodeld/ModelAv1.xcdatamodel/contents और ModelB.xcdatamodeld/ModelBv1_merge.xcdatamodel/contents) में ModelAv1 और ModelBv1_merge के लिए XML सामग्री खोलें और एक्सएमएल को हाथ से मर्ज करें। स्कीमा बहुत सरल है - बस <entity> तत्वों की प्रतिलिपि बनाएँ और <elements> तत्व (_merge सामग्री फ़ाइल में) मर्ज करें और आप कर चुके हैं।

  3. अपने नए मॉडल बीवी 2 के लिए सामग्री फ़ाइल खोलें और फिर इसमें मॉडल ए सामग्री को मर्ज करें।

  4. अपनी प्रोजेक्ट फ़ाइल से ModelA निकालें। Xcode में

चेक कि ModelBv1_merge और ModelBv2 समझदार लग रहे हैं, और सब कुछ आप उम्मीद कर (पुराने मॉडल ए और मॉडल बी के संघ) होते हैं।बनाएँ और आपको किया जाना चाहिए।

(मुझे लगता है कि यह दोनों की एक चेतावनी है "प्रदान की गई दोनों सामग्री फाइलों को एक्सकोड के समान संस्करण द्वारा लिखा गया था", लेकिन मुझे लगता है कि यदि आपके पास पुरानी सामग्री फ़ाइल है तो यह एक्सकोड को फिर से लिखने के लिए पर्याप्त आसान होना चाहिए मामूली परिवर्तन कहीं भी।)

+0

अभी भी रखने के लिए हैकस्टिक तरीका 2 डेटा मॉडल फाइलें हैं (भले ही केवल अस्थायी रूप से! धन्यवाद! :) – Mark

+0

बहुत बढ़िया। मेरे बेकन बचाया। धन्यवाद – Darren

+0

हैलो, इस तरह सिम्युलेटर पर बहुत अच्छा काम कर रहा है लेकिन यह डिवाइस पर काम नहीं कर रहा है ?? –

5

मैं एक परिदृश्य है, जिसमें अपने आवेदन मॉडल प्राप्त अनेक मॉडल विलय है, और मैं इस तरह से स्वत: हल्के प्रवास का एक प्रकार है करने में कामयाब रहे:

NSError* error = nil; 
NSURL *documentsDirectory = [[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] lastObject]; 
NSURL *storeURL = [documentsDirectory URLByAppendingPathComponent:@"db.sqlite"]; 
NSString* storePath = [storeURL path]; 
NSLog(@"Store URL: %@", storeURL); 
if([[NSFileManager defaultManager] fileExistsAtPath:storePath]){ 
    // Load store metadata (this will contain information about the versions of the models this store was created with) 
    NSDictionary *storeMeta = [NSPersistentStoreCoordinator metadataForPersistentStoreOfType:nil URL:storeURL error:&error]; 
    if(storeMeta){ 
     // Get the current model, merging all the models in the main bundle (in their current version) 
     NSManagedObjectModel* model=[NSManagedObjectModel mergedModelFromBundles:nil]; 
     // If the persistent store is not compatible with such a model (i.e. it was created with a model obtained merging old versions of "submodels"), migrate 
     if(![model isConfiguration:nil compatibleWithStoreMetadata:storeMeta]){ 


      // Load the old model 
      NSManagedObjectModel*oldModel = [NSManagedObjectModel mergedModelFromBundles:nil forStoreMetadata:storeMeta]; 

      // Compute the mapping between old model and new model 
      NSMappingModel* mapping = [NSMappingModel inferredMappingModelForSourceModel:oldModel destinationModel:model error:&error]; 
      if(mapping){ 
       // Backup old store 
       NSURL* storeBackupURL = [[self applicationDocumentsDirectory] URLByAppendingPathComponent:[NSString stringWithFormat:@"db.sqlite.%@.bck", [NSDate new]]]; 
       BOOL done = [[NSFileManager defaultManager] moveItemAtURL:storeURL toURL:storeBackupURL error:&error]; 
       if(done){ 
        // Apply the mapping 
        NSMigrationManager* migrationManager = [[NSMigrationManager alloc] initWithSourceModel:oldModel destinationModel:model]; 
        BOOL done = [migrationManager migrateStoreFromURL: storeBackupURL 
                   type: NSSQLiteStoreType 
                   options: nil 
                withMappingModel: mapping 
                toDestinationURL: storeURL 
                 destinationType: NSSQLiteStoreType 
                destinationOptions: nil 
                   error: &error]; 
        if(done){ 
         NSLog(@"Store migration successful!!!"); 
        } 
       } 
      } 
     } 
    } 
} 

if(error){ 
    NSLog(@"Migration error: %@", error); 
} 
+0

मैंने आपके जवाब को पढ़ने से पहले खुद को एक ही कोड लिखने में पाया है। हालांकि बदसूरत, ऐसा करने का एकमात्र तरीका ऐसा लगता है। –

+0

वाह, धन्यवाद, मैं इस समस्या के साथ घंटों तक फंस गया हूं। सिर्फ एक सवाल, क्या आप सभी बैकअप फाइलें रखते हैं? माइग्रेशन किए जाने के बाद मुझे लगता है कि – Leonardo

+0

वाह को हटाने में कोई हानि नहीं है, यह वास्तव में मेरे गधे को बचाता है। बहुत बहुत धन्यवाद!! मेरा विशिष्ट मुद्दा यह था कि हमने एक विरासत ऐप से मैन्युअल माइग्रेशन के लिए एक पुराना xcdatamodeld था, और एक उचित संस्करण नया xcdatamodeld था। मुझे लगता है कि कोर डेटा इस पर चिल्ला रहा था। –

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