永久NSManagedObjectID不那么永久? [英] Permanent NSManagedObjectID not so permanent?

查看:153
本文介绍了永久NSManagedObjectID不那么永久?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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



我的目标是在工作上下文中创建一个对象,保存到持久存储,将它的objectID URL保存到NSUserDefaults,然后能够使用objectID拉出该MO 。但是,我发现在保存对象的永久ID后改变。



在控制台输出下面你可以看到,我请求永久ID我回来的值是F474F6EE-A225-456B-92EF-AB1407336F15 / CDBaseAccount / p1,但后来当我列出所有的对象在CD中唯一的对象有IDF474F6EE-A225-456B-92EF-AB1407336F15 / CDBaseAccount / p2。 p1和p2,发生了什么?



代码:

  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 = persistentStoreCoordinator managedObjectIDForURIRepresentation:u];
NSError * objWithIdError = nil;
NSManagedObject * o = [d existingObjectWithID:i error:& objWithIdError];
if(objWithIdError!= nil){
NSLog(@现有对象错误:%@,objWithIdError);
return;
}

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

});
}];

控制台输出:

 > + [NSManagedObjectContext(MagicalRecord)MR_contextWithStoreCoordinator:](0xa7c9b0) - > Created< NSManagedObjectContext:0x83522a0> ;:上下文***主线程*** 
> count:0
>所有帐户=(
>)
> - [NSManagedObjectContext(MagicalSaves)MR_saveWithErrorCallback:](0x8353de0) - >保存< NSManagedObjectContext:0x8353de0> ;:上下文*** MAIN THREAD ***
> - [NSManagedObjectContext(MagicalSaves)MR_saveWithErrorCallback:](0x8195450) - >保存< NSManagedObjectContext:0x8195450> ;: *** DEFAULT ***上下文***主线程***
> - [NSManagedObjectContext(MagicalSaves)MR_saveWithErrorCallback:](0x83522a0) - >保存< NSManagedObjectContext:0x83522a0> ;: ***后保存***上下文***主线程***
> 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
>所有帐户=(
< CDBaseAccount:0x844ca60>(实体:CDBaseAccount; id:0x844a4c0< x-coredata:// F474F6EE-A225-456B-92EF-AB1407336F15 / CDBaseAccount / p1& fault>)

>现有对象错误:错误域= NSCocoaErrorDomain代码= 133000无法完成该操作。(可能错误133000.)UserInfo = 0x864d8c0 {NSAffectedObjectsErrorKey =(
(entity:CDBaseAccount; id:0x86405c0< x-coredata:// F474F6EE-A225-456B-92EF-AB1407336F15 / CDBaseAccount / p2> ;; data:< fault>)
)}


解决方案

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



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


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

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

处理 -objectID 作为永久唯一标识符存储在持久存储外面将会失败你经常。核心数据在对象的生命周期内多次更改 -objectID 的底层详细信息。



如果需要一个外部可靠的唯一的,那么你需要自己创建一个。我一般建议向任何需要外部引用唯一的实体添加 [[NSProcessInfo processInfo] worldwideUniqueString] -awakeFromInsert 是一个很棒的地方。


I'm having trouble dealing with object IDs in CoreData. I'm using MagicalRecord for convenience and have 3 contexts: a private queue working context, a main queue context for UI and parent to the working context, and a private queue saving context that is the parent of the main context.

My goal is to create an object in the working context, save to the persistent store, save it's objectID URL to NSUserDefaults, and then be able to pull out that MO using the objectID later on. However, what I'm finding is that after saving the permanent ID of the object is changing.

In the console output below you can see that after I request the permanent ID the value I get back is "F474F6EE-A225-456B-92EF-AB1407336F15/CDBaseAccount/p1" but later when I list all the objects in CD the only object there has the ID "F474F6EE-A225-456B-92EF-AB1407336F15/CDBaseAccount/p2". p1 vs p2, what happened?

Code:

  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);

      });
  }];

Console output:

  > +[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>)"
  )}

解决方案

Short answer is, don't do that :)

-objectID is not reliable between launches of your application. It is guaranteed to be unique and reliable under the following conditions:

  1. Within a single lifecycle of the application
  2. In its original object form (not in URL or NSString form)

Treating the -objectID as a permanent unique identifier to be stored outside of the persistent store is going to fail you fairly often. Core Data changes the underlying details of the -objectID many times during the life of the object.

If you need an externally reliable unique then you need to create one yourself. I generally recommend adding a [[NSProcessInfo processInfo] globallyUniqueString] to any entity that needs an externally reference-able unique. -awakeFromInsert is a great place to do that.

这篇关于永久NSManagedObjectID不那么永久?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆