2012-08-31 15 views
8

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

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

नीचे कंसोल आउटपुट में आप देख सकते हैं कि मैं स्थायी आईडी का अनुरोध करने के बाद मूल्य वापस प्राप्त करता हूं "F474F6EE-A225-456B-92EF-AB1407336F15/CDBaseAccount/p1" लेकिन बाद में जब मैं सीडी में सभी ऑब्जेक्ट्स सूचीबद्ध करता हूं एकमात्र वस्तु में आईडी "F474F6EE-A225-456B-92EF-AB1407336F15/CDBaseAccount/p2" है। पी 1 बनाम पी 2, क्या हुआ?

कोड:

NSManagedObjectContext *c = [NSManagedObjectContext MR_contextThatPushesChangesToDefaultContext]; 
    [c performBlockAndWait:^{ 

     NSArray *all = [CDBaseAccount MR_findAllInContext:c]; 
     NSLog(@"count: %d", all.count); 
     NSLog(@"all accounts = %@", all); 

     CDBaseAccount *a = [CDBaseAccount MR_createInContext:c]; 
     a.accountName = @"foo"; 

     [c MR_saveNestedContexts]; 

     NSLog(@"temp a.objectID = %@", a.objectID); 

     NSError *error; 
     if (![c obtainPermanentIDsForObjects:@[a] error:&error]) { 
      NSLog(@"perm id error: %@", error); 
      return; 
     } 

     NSLog(@"perm a.objectID = %@", a.objectID); 

     NSURL *u = a.objectID.URIRepresentation; 

     dispatch_async(dispatch_get_main_queue(), ^{ 
      NSManagedObjectContext *d = [NSManagedObjectContext MR_defaultContext]; 

      NSArray *all = [CDBaseAccount MR_findAllInContext:d]; 
      NSLog(@"count: %d", all.count); 
      NSLog(@"all accounts = %@", all); 

      NSManagedObjectID *i = [d.persistentStoreCoordinator managedObjectIDForURIRepresentation:u]; 
      NSError *objWithIdError = nil; 
      NSManagedObject *o = [d existingObjectWithID:i error:&objWithIdError]; 
      if (objWithIdError != nil) { 
       NSLog(@"existing object error: %@", objWithIdError); 
       return; 
      } 

      NSLog(@"o = %@", o); 
      NSLog(@"o.objectID = %@", o.objectID); 

     }); 
    }]; 

कंसोल आउटपुट:

> +[NSManagedObjectContext(MagicalRecord) MR_contextWithStoreCoordinator:](0xa7c9b0) -> Created <NSManagedObjectContext: 0x83522a0>: Context *** MAIN THREAD *** 
    > count: 0 
    > all accounts = (
    >) 
    > -[NSManagedObjectContext(MagicalSaves) MR_saveWithErrorCallback:](0x8353de0) -> Saving <NSManagedObjectContext: 0x8353de0>: Context *** MAIN THREAD *** 
    > -[NSManagedObjectContext(MagicalSaves) MR_saveWithErrorCallback:](0x8195450) -> Saving <NSManagedObjectContext: 0x8195450>: *** DEFAULT *** Context *** MAIN THREAD *** 
    > -[NSManagedObjectContext(MagicalSaves) MR_saveWithErrorCallback:](0x83522a0) -> Saving <NSManagedObjectContext: 0x83522a0>: *** BACKGROUND SAVE *** Context *** MAIN THREAD *** 
    > temp a.objectID = 0x8187ee0 <x-coredata:///CDBaseAccount/tF392AC6A-3539-4F39-AC53-35F9E5B3C9322> 
    > perm a.objectID = 0x8355800 <x-coredata://F474F6EE-A225-456B-92EF-AB1407336F15/CDBaseAccount/p2> 
    > count: 1 
    > all accounts = (
     "<CDBaseAccount: 0x844ca60> (entity: CDBaseAccount; id: 0x844a4c0 <x-coredata://F474F6EE-A225-456B-92EF-AB1407336F15/CDBaseAccount/p1> ; data: <fault>)" 
) 
    > existing object error: Error Domain=NSCocoaErrorDomain Code=133000 "The operation couldn’t be completed. (Cocoa error 133000.)" UserInfo=0x864d8c0 {NSAffectedObjectsErrorKey=(
     "<CDBaseAccount: 0x864b8c0> (entity: CDBaseAccount; id: 0x86405c0 <x-coredata://F474F6EE-A225-456B-92EF-AB1407336F15/CDBaseAccount/p2> ; data: <fault>)" 
)} 

उत्तर

18

कम जवाब है, कि :)

-objectID अपने आवेदन की शुरूआत के बीच विश्वसनीय नहीं है ऐसा नहीं करते हैं।

  1. आवेदन
  2. अपने मूल वस्तु रूप में

(URL या NSString रूप में नहीं) के उपचार की एक एकल जीवन चक्र के भीतर: यह अद्वितीय और निम्नलिखित परिस्थितियों में विश्वसनीय होने की गारंटी है -objectID लगातार स्टोर के बाहर संग्रहीत करने के लिए एक स्थायी अद्वितीय पहचानकर्ता के रूप में आपको काफी बार विफल होने जा रहा है। कोर डेटा ऑब्जेक्ट के जीवन के दौरान -objectID के अंतर्निहित विवरणों को बदलता है।

यदि आपको बाहरी रूप से विश्वसनीय अद्वितीय की आवश्यकता है तो आपको स्वयं को एक बनाने की आवश्यकता है। मैं आमतौर पर किसी भी इकाई को [[NSProcessInfo processInfo] globallyUniqueString] जोड़ने की अनुशंसा करता हूं जिसे बाहरी संदर्भ-सक्षम अद्वितीय की आवश्यकता होती है। -awakeFromInsert ऐसा करने के लिए एक शानदार जगह है।

+0

धन्यवाद, इतना मार्कस! सभी दस्तावेजों में 'स्थायी' शब्द शब्द वास्तव में धोखा दे रहा है। मुझे उम्मीद है कि आप अपनी सीडी बुक का एक नया संस्करण डाल देंगे, क्योंकि पुराना ओओपी है। 'GloballyUniqueString' – brianpartridge

+1

+1 यदि आप' NSManagedObjectID' को लॉन्च करते हैं, तो ऐप लॉन्च किए गए 'समकालीन आईडी' में 'NO'' लौटाता है, तो आप निश्चित रूप से कुछ स्केची कर रहे हैं। यह मेरे लिए बहुत अच्छा काम करता है और लंबे समय से ऐसा करता है। –

+1

के लिए –

0

ऐसा इसलिए हो सकता है क्योंकि आप नेस्टेड संदर्भ का उपयोग कर रहे हैं।

#import <Foundation/Foundation.h> 
#import <CoreData/CoreData.h> 

static NSArray *fetchAllPersons(NSManagedObjectContext *moc); 
static NSManagedObjectModel *managedObjectModel(); 
static NSManagedObjectContext *createManagedObjectContext(); 
static NSURL *desktopDirectoryURL(void); 

static void testObjectID(void); 



int main(int argc, const char * argv[]) 
{ 
    @autoreleasepool { 
     dispatch_async(dispatch_get_global_queue(0, 0), ^{ 
      testObjectID(); 
     }); 
    } 
    dispatch_main(); 
    return 0; 
} 




static void testObjectID(void) 
{ 
    NSManagedObjectContext *c = createManagedObjectContext(); 
    [c performBlock:^{ 

     NSArray *all = fetchAllPersons(c); 
     NSLog(@"count: %lu", all.count); 
     NSLog(@"all accounts = %@", all); 

     NSManagedObject *a = [NSEntityDescription insertNewObjectForEntityForName:@"Person" inManagedObjectContext:c]; 
     [a setValue:@"foo" forKey:@"name"]; 

     NSLog(@"temp a.objectID = %@", a.objectID); 
     NSError *error = nil; 
     NSCAssert([c obtainPermanentIDsForObjects:@[a] error:&error], @"perm id error: %@", error); 
     NSLog(@"perm a.objectID = %@", a.objectID); 

     NSCAssert([c save:&error], @"Save failed: %@", error); 

     NSURL *u = a.objectID.URIRepresentation; 

     dispatch_async(dispatch_get_global_queue(0, 0), ^{ 
      NSManagedObjectContext *d = createManagedObjectContext(); 

      NSArray *all = fetchAllPersons(c); 
      NSLog(@"count: %lu", all.count); 
      NSLog(@"all accounts = %@", all); 

      NSManagedObjectID *i = [d.persistentStoreCoordinator managedObjectIDForURIRepresentation:u]; 
      NSError *objWithIdError = nil; 
      NSManagedObject *o = [d existingObjectWithID:i error:&objWithIdError]; 
      NSCAssert(o != nil, @"existing object error: %@", objWithIdError); 

      NSLog(@"o = %@", o); 
      NSLog(@"o.objectID = %@", o.objectID); 
     }); 
    }]; 
} 


static NSArray *fetchAllPersons(NSManagedObjectContext *moc) 
{ 
    NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:@"Person"]; 
    NSError *error = nil; 
    NSArray *result = [moc executeFetchRequest:request error:&error]; 
    NSCAssert(result != nil, @"Fetch failed: %@", error); 
    return result; 
} 

static NSManagedObjectModel *managedObjectModel() 
{ 
    static NSManagedObjectModel *mom = nil; 
    static dispatch_once_t onceToken; 
    dispatch_once(&onceToken, ^{ 
     NSEntityDescription *personEntity = [[NSEntityDescription alloc] init]; 
     [personEntity setName:@"Person"]; 

     NSAttributeDescription *nameAttribute = [[NSAttributeDescription alloc] init]; 

     [nameAttribute setName:@"name"]; 
     [nameAttribute setAttributeType:NSStringAttributeType]; 

     [personEntity setProperties:@[nameAttribute]]; 

     mom = [[NSManagedObjectModel alloc] init]; 
     [mom setEntities:@[personEntity]]; 
    }); 
    return mom; 
} 


static NSManagedObjectContext *createManagedObjectContext() 
{ 
    static NSPersistentStoreCoordinator *coordinator; 
    static dispatch_once_t onceToken; 
    dispatch_once(&onceToken, ^{ 
     coordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel: managedObjectModel()]; 

     NSString *STORE_TYPE = NSSQLiteStoreType; 
     NSString *STORE_FILENAME = @"foobar.db"; 

     NSError *error; 
     NSURL *url = [desktopDirectoryURL() URLByAppendingPathComponent:STORE_FILENAME]; 

     NSPersistentStore *newStore = [coordinator addPersistentStoreWithType:STORE_TYPE 
                   configuration:nil URL:url options:nil 
                     error:&error]; 

     if (newStore == nil) { 
      NSLog(@"Store Configuration Failure\n%@", 
        ([error localizedDescription] != nil) ? 
        [error localizedDescription] : @"Unknown Error"); 
     } 
    }); 

    NSManagedObjectContext *moc = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType]; 
    [moc setPersistentStoreCoordinator:coordinator]; 

    return moc; 
} 


static NSURL *desktopDirectoryURL(void) 
{ 
    static NSURL *URL; 
    static dispatch_once_t onceToken; 
    dispatch_once(&onceToken, ^{ 
     NSFileManager *fileManager = [[NSFileManager alloc] init]; 
     NSError *error; 
     URL = [fileManager URLForDirectory:NSDesktopDirectory inDomain:NSUserDomainMask appropriateForURL:nil create:YES error:&error]; 
     NSCAssert(URL != nil, @"Could not access Desktop directory: %@", [error localizedDescription]); 
    }); 
    return URL; 
} 

आउटपुट:

count: 0 
all accounts = (
) 
temp a.objectID = 0x10180e640 <x-coredata:///Person/tB1D48677-0152-4DA9-8573-7C7532863B4E2> 
perm a.objectID = 0x101901bb0 <x-coredata://275C90E5-2598-4DFA-BF4C-E60A336E8BE4/Person/p1> 
count: 1 
all accounts = (
    "<NSManagedObject: 0x10180e5b0> (entity: Person; id: 0x101901bb0 <x-coredata://275C90E5-2598-4DFA-BF4C-E60A336E8BE4/Person/p1> ; data: {\n name = foo;\n})" 
) 
o = <NSManagedObject: 0x100416530> (entity: Person; id: 0x100415b60 <x-coredata://275C90E5-2598-4DFA-BF4C-E60A336E8BE4/Person/p1> ; data: { 
    name = foo; 
}) 
o.objectID = 0x100415b60 <x-coredata://275C90E5-2598-4DFA-BF4C-E60A336E8BE4/Person/p1> 
+0

हाँ, यह वह व्यवहार है जिसकी मैं अपेक्षा कर रहा था। शायद यह नेस्टेड संदर्भों से संबंधित है। – brianpartridge

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