CoreData + RESTKit:来自NSFetchedResultsController的同一对象的多个副本

时间:2014-02-15 13:46:17

标签: objective-c core-data ios7 restkit restkit-0.20

我正在使用相同的NSFetchedResultsController从sqllite支持的核心数据中获取一些结果,这些结果通过RESTKit在多个视图控制器之间共享:

NSFetchedResultsController* _fetchedResultsController;

NSFetchRequest *fetchRequest = [NSFetchRequest fetchRequestWithEntityName:@"User"];
fetchRequest.sortDescriptors = @[[[NSSortDescriptor alloc] initWithKey:@"username" ascending:YES]];
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"current == YES"];
[fetchRequest setPredicate:predicate];
_fetchedResultsController =
[[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest
                                    managedObjectContext:[self __getContext]
                                      sectionNameKeyPath:nil cacheName:@"currentUser"];
_fetchedResultsController.delegate = self;
[_fetchedResultsController performFetch:error];
NSArray *array = [_fetchedResultsController fetchedObjects];
return array;

这是在应用程序执行期间的多个阶段调用的,但是尽管我指定了一个缓存名称,但我得到了同一个对象的多个副本,即不是单一的事实来源。

此问题仅在重新加载应用时发生。初始映射对象不是问题。

我错过了什么吗?提前致谢

编辑:

首先是一些背景:

我使用当前属性标记当前登录的用户,并且任何需要访问当前用户的视图控制器都将执行缓存的提取请求。

在应用程序的早期某个时刻,一个视图控制器将自己添加为从此获取请求接收的当前用户的观察者。在应用程序执行的另一个点上,用户创建一个专辑,此时再次执行获取请求。这次对象的内存地址不同,并且当相册添加到用户集属性时,第一个视图控制器不会收到KVO通知。

以下是一些额外的日志,显示RKInMemoryManagedObjectCache开始返回另一个User对象:

2014-02-15 16:15:53.196 [22074:a0b] user init: 0xf090b60 <x-coredata://56C4885F-954C-4843-9A59-52133777ECC5/User/p2><robbie> in context <NSManagedObjectContext: 0xf079790>
2014-02-15 16:15:53.198 [22074:a0b] [<RKInMemoryManagedObjectCache: 0xf0593b0>] In memory object cache is returning 0xf090b60 <x-coredata://56C4885F-954C-4843-9A59-52133777ECC5/User/p2><robbie> as current user
2014-02-15 16:15:53.209 [22074:a0b] [<RKInMemoryManagedObjectCache: 0xf0593b0>] In memory object cache is returning 0xf090b60 <x-coredata://56C4885F-954C-4843-9A59-52133777ECC5/User/p2><robbie> as current user
2014-02-15 16:15:53.209 [22074:a0b] [AlbumCollectionViewController] observing user 0xf090b60 <x-coredata://56C4885F-954C-4843-9A59-52133777ECC5/User/p2>: robbie
2014-02-15 16:15:53.209 [22074:a0b] [<RKInMemoryManagedObjectCache: 0xf0593b0>] In memory object cache is returning 0xf090b60 <x-coredata://56C4885F-954C-4843-9A59-52133777ECC5/User/p2><robbie> as current user
2014-02-15 16:15:53.262 [22074:a0b] [<RKInMemoryManagedObjectCache: 0xf0593b0>] In memory object cache is returning 0xf090b60 <x-coredata://56C4885F-954C-4843-9A59-52133777ECC5/User/p2><robbie> as current user
2014-02-15 16:15:53.262 [22074:a0b] [<RKInMemoryManagedObjectCache: 0xf0593b0>] In memory object cache is returning 0xf090b60 <x-coredata://56C4885F-954C-4843-9A59-52133777ECC5/User/p2><robbie> as current user
2014-02-15 16:15:53.269 [22074:a0b] [<RKInMemoryManagedObjectCache: 0xf0593b0>] In memory object cache is returning 0xf090b60 <x-coredata://56C4885F-954C-4843-9A59-52133777ECC5/User/p2><robbie> as current user
2014-02-15 16:15:53.269 [22074:a0b] [<RKInMemoryManagedObjectCache: 0xf0593b0>] In memory object cache is returning 0xf090b60 <x-coredata://56C4885F-954C-4843-9A59-52133777ECC5/User/p2><robbie> as current user
2014-02-15 16:15:53.278 [22074:a0b] applicationDidBecomeActive
2014-02-15 16:15:53.329 [22074:a0b] user init: 0xf342590 <x-coredata://56C4885F-954C-4843-9A59-52133777ECC5/User/p2><robbie> in context <NSManagedObjectContext: 0xf079790>
2014-02-15 16:15:53.329 [22074:a0b] [<RKInMemoryManagedObjectCache: 0xf0593b0>] In memory object cache is returning 0xf342590 <x-coredata://56C4885F-954C-4843-9A59-52133777ECC5/User/p2><robbie> as current user
2014-02-15 16:15:53.329 [22074:a0b] [<RKInMemoryManagedObjectCache: 0xf0593b0>] In memory object cache is returning 0xf342590 <x-coredata://56C4885F-954C-4843-9A59-52133777ECC5/User/p2><robbie> as current user
2014-02-15 16:15:53.346 [22074:a0b] [<RKInMemoryManagedObjectCache: 0xf0593b0>] In memory object cache is returning 0xf342590 <x-coredata://56C4885F-954C-4843-9A59-52133777ECC5/User/p2><robbie> as current user
2014-02-15 16:15:53.348 [22074:a0b] [<RKInMemoryManagedObjectCache: 0xf0593b0>] In memory object cache is returning 0xf342590 <x-coredata://56C4885F-954C-4843-9A59-52133777ECC5/User/p2><robbie> as current user

奇怪的是,一旦调用了applicationDidBecomeActive,似乎总是会返回不同的东西。

EDIT2:

调用堆栈导致第一个用户初始化:

#0  0x000e87f0 in -[User initWithEntity:insertIntoManagedObjectContext:] at /Users/mtford/Playground/App/App/App/CoreData/Human/User.m:107
#1  0x00f68a89 in -[NSManagedObject(_NSInternalMethods) _initWithEntity:withID:withHandler:withContext:] ()
#2  0x00f66ff2 in -[NSManagedObjectContext(_NSInternalAdditions) _retainedObjectWithID:optionalHandler:withInlineStorage:] ()
#3  0x00fb69b4 in _PFRetainedObjectIDCore ()
#4  0x00fb6880 in -[NSManagedObjectContext(_NSInternalAdditions) _retainedObjectWithID:] ()
#5  0x00fa7724 in -[NSManagedObjectContext(_NestedContextSupport) _parentObjectsForFetchRequest:inContext:error:] ()
#6  0x010251f4 in __82-[NSManagedObjectContext(_NestedContextSupport) executeRequest:withContext:error:]_block_invoke ()
#7  0x00fa7321 in internalBlockToNSManagedObjectContextPerform ()
#8  0x035fb4b0 in _dispatch_client_callout ()
#9  0x035e8778 in _dispatch_barrier_sync_f_invoke ()
#10 0x035e8422 in dispatch_barrier_sync_f ()
#11 0x00fa72a2 in _perform ()
#12 0x00fa714e in -[NSManagedObjectContext(_NestedContextSupport) executeRequest:withContext:error:] ()
#13 0x00f526c6 in -[NSManagedObjectContext executeFetchRequest:error:] ()
#14 0x00276367 in __96-[RKInMemoryManagedObjectCache managedObjectsWithEntity:attributeValues:inManagedObjectContext:]_block_invoke_2 at /Users/mtford/Playground/App/App/Pods/RestKit/Code/CoreData/RKInMemoryManagedObjectCache.m:112
#15 0x00fa6fef in developerSubmittedBlockToNSManagedObjectContextPerform ()
#16 0x00fa6f2c in -[NSManagedObjectContext performBlockAndWait:] ()
#17 0x00275ce4 in -[RKInMemoryManagedObjectCache managedObjectsWithEntity:attributeValues:inManagedObjectContext:] at /Users/mtford/Playground/App/App/Pods/RestKit/Code/CoreData/RKInMemoryManagedObjectCache.m:109
#18 0x000d73d9 in -[RestKitInterface getCurrentUsersWithError:] at /Users/mtford/Playground/App/App/App/RESTKit/Old/RestKitInterface.m:647
#19 0x000e9613 in +[User currentUser] at /Users/mtford/Playground/App/App/App/CoreData/Human/User.m:221
#20 0x0002f6f0 in -[TabBarController viewWillAppear:] at /Users/mtford/Playground/App/App/App/View Controllers/AppTabBarController.m:100

调用堆栈导致第二个用户初始化:

#0  0x000e87f0 in -[User initWithEntity:insertIntoManagedObjectContext:] at /Users/mtford/Playground/App/App/App/CoreData/Human/User.m:107
#1  0x00f68a89 in -[NSManagedObject(_NSInternalMethods) _initWithEntity:withID:withHandler:withContext:] ()
#2  0x00f66ff2 in -[NSManagedObjectContext(_NSInternalAdditions) _retainedObjectWithID:optionalHandler:withInlineStorage:] ()
#3  0x00fb69b4 in _PFRetainedObjectIDCore ()
#4  0x00f7ffbf in -[NSManagedObjectContext(_NSInternalAdditions) _retainedObjectWithID:error:] ()
#5  0x00f7fef5 in -[NSManagedObjectContext existingObjectWithID:error:] ()
#6  0x0025e29a in __56-[RKEntityByAttributeCache objectForObjectID:inContext:]_block_invoke at /Users/mtford/Playground/App/App/Pods/RestKit/Code/CoreData/RKEntityByAttributeCache.m:222
#7  0x00fa6fef in developerSubmittedBlockToNSManagedObjectContextPerform ()
#8  0x00fa6f2c in -[NSManagedObjectContext performBlockAndWait:] ()
#9  0x0025dd7c in -[RKEntityByAttributeCache objectForObjectID:inContext:] at /Users/mtford/Playground/App/App/Pods/RestKit/Code/CoreData/RKEntityByAttributeCache.m:221
#10 0x0025ea74 in -[RKEntityByAttributeCache objectsWithAttributeValues:inContext:] at /Users/mtford/Playground/App/App/Pods/RestKit/Code/CoreData/RKEntityByAttributeCache.m:255
#11 0x00265644 in -[RKEntityCache objectsForEntity:withAttributeValues:inContext:] at /Users/mtford/Playground/App/App/Pods/RestKit/Code/CoreData/RKEntityCache.m:90
#12 0x00275f15 in -[RKInMemoryManagedObjectCache managedObjectsWithEntity:attributeValues:inManagedObjectContext:] at /Users/mtford/Playground/App/App/Pods/RestKit/Code/CoreData/RKInMemoryManagedObjectCache.m:132
#13 0x000d73d9 in -[RestKitInterface getCurrentUsersWithError:] at /Users/mtford/Playground/App/App/App/RESTKit/Old/RestKitInterface.m:647
#14 0x000e9613 in +[User currentUser] at /Users/mtford/Playground/App/App/App/CoreData/Human/User.m:221
#15 0x00003efb in -[AlbumCollectionViewController observeValueForKeyPath:ofObject:change:context:] at /Users/mtford/Playground/App/App/App/View Controllers/AlbumCollectionViewController.m:179

1 个答案:

答案 0 :(得分:0)

在我们使用RESTKit和CoreData的项目中,我们也遇到了相同的重复问题,避免重复的最简单方法是使用setIdentificationAttributes

为实体映射设置唯一的id参数