首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >永久NSManagedObjectID不是永久的吗?

永久NSManagedObjectID不是永久的吗?
EN

Stack Overflow用户
提问于 2012-08-31 23:28:25
回答 2查看 5.2K关注 0票数 11

我在处理CoreData中的对象in时遇到了问题。为了方便起见,我使用了MagicalRecord,并且有3个上下文:私有队列工作上下文、用于UI的主队列上下文和工作上下文的父上下文,以及作为主上下文的父上下文的私有队列保存上下文。

我的目标是在工作上下文中创建一个对象,保存到持久化存储,将它的objectID URL保存到NSUserDefaults,然后能够稍后使用objectID提取该MO。然而,我发现在保存之后,对象的永久ID正在发生变化。

在下面的控制台输出中,您可以看到,在我请求永久ID之后,我得到的值是"F474F6EE-A225-456B-92EF-AB1407336F15/CDBaseAccount/p1“,但是稍后当我列出CD中的所有对象时,其中唯一的对象的ID是"F474F6EE-A225-456B-92EF-AB1407336F15/CDBaseAccount/p2".p1 vs p2,发生了什么?

代码:

代码语言:javascript
复制
  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);

      });
  }];

控制台输出:

代码语言:javascript
复制
  > +[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>)"
  )}
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2012-08-31 23:38:06

简单的回答是,不要这样做:)

在应用程序启动之间,-objectID是不可靠的。在以下条件下,保证其唯一性和可靠性:

应用程序的单个生命周期内的

  1. 以其原始对象形式(不是URL或NSString形式)

-objectID作为永久的惟一标识符存储在持久存储之外,这会经常让您失败。核心数据在对象的生命周期内多次更改-objectID的底层详细信息。

如果您需要一个外部可靠的唯一,那么您需要自己创建一个。我通常建议将[[NSProcessInfo processInfo] globallyUniqueString]添加到任何需要可外部引用的唯一实体中。-awakeFromInsert是一个很好的地方。

票数 21
EN

Stack Overflow用户

发布于 2012-09-01 21:56:04

这可能是因为您使用的是嵌套上下文。

代码语言:javascript
复制
#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;
}

输出:

代码语言:javascript
复制
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>
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/12218396

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档