哎呀,对不起这么长的头衔.
我有一个托管对象上下文,我存储从两个不同位置派生的歌曲.我从手机上的持久存储中获取了一些歌曲(使用Core Data),我从在线数据库中提取了一些歌曲.这两首歌都属于同一个MananagedObject子类.我想这两个歌曲是在一个单一的情况下,因为我想他们两个出现在与NSFetchedResultsController连接的表视图.
当我想保存其中一首歌时会出现问题.我不想将从在线数据库中提取的所有歌曲保存到手机中.我只想保存单曲,所以简单的[moc save]不起作用.另一个问题是,在我保存单曲之后,我仍然希望从在线播放的歌曲在上下文中(但是再次,不保存).我相信我有几个不同的选择:
1)是否可以将NSFetchedResults控制器连接到多个上下文?
2)我可以将从在线数据库中提取的所有歌曲移动到单独的临时上下文中,保存在原始上下文中,然后将所有歌曲移回.(请参阅:如何将NSManagedObject从一个上下文复制或移动到另一个上下文?)
3)记住在线歌曲的所有键值对,从上下文中删除在线歌曲,保存原始上下文,根据保存的键值对将所有在线歌曲插回到原始上下文中.
4)我是一个巨大的n00b,我更容易丢失一些东西.
谢谢!
core-data nsfetchedresultscontroller nsmanagedobject nsmanagedobjectcontext ios
我从文档和这个答案中的理解是,如果数据存在,NSManagedObjectContext existingObjectWithID:error:和objectWithID:方法应返回相同的对象,但是当数据不存在时,existingObjectWithID:error:将返回nil同时objectWithID:返回具有错误而不是数据的对象.
我在应用程序中看到的是一个实例,其中(在子管理对象上下文中的后台线程上创建对象并保存,然后转到主线程,保存并将对象ID从子上下文带到父对象上下文),existingObjectWithID:error:返回nil,但objectWithID:返回具有有效数据的实际可用对象,而不是故障.
我对这两种方法的理解不正确吗?难道我做错了什么?
(我想要nil返回-when-there-no-data行为existingObjectWithID:error:,但是无法获取新创建的对象的数据是有问题的.)
编辑:我想我可以使用objectWithID:,然后立即测试访问try-catch块中返回对象的属性,捕获抛出的异常,并替换伪造的对象nil(如此处所做),但try-catch是昂贵的Objective-C这似乎是一个非常糟糕的主意.
我正在尝试删除托管对象上下文,但不是删除对象本身,而是将所有即时变量设置为null.在删除NSManagedObjectContext的瞬间时,我做错了什么?
@implementation MyManagedObject
- (BOOL)submitToServer
{
if (/*submitted successfully*/)
{
return YES;
}
else
{
[self.managedObjectContext deleteObject:self];
return NO;
}
}
@end
Run Code Online (Sandbox Code Playgroud) 当我尝试从服务器发送的数据构建初始数据库时,我遇到了基于CoreData的iOS应用程序的问题.基本上,服务器发送1MB的对象块(每个块约3,000个),iOS客户端对它们进行反序列化并将它们写入磁盘.
我所看到的是,对于前8个块(44个)中的一切都进展顺利,然后性能急剧下降,每个块开始花费的时间越来越长,如下图所示.[NSManagedObjectContext save]正如您在仪器分析数据中看到的那样,几乎所有时间都消耗掉了,但似乎应用程序由于某种原因不再以100%的CPU运行,就像它正在等待磁盘I/O或其他东西一样.

关于我是如何做到的一些重要事实:
每个块在其自身的处理NSManagedObjectContext与它自己的NSAutoreleasePool,所以没有对象积聚在组块的处理之间的非冲洗上下文.
NSUndoManager任何情境都没有设定.
没有mergeChangesFromContextDidSaveNotification:进行(即块上下文没有将其更改推送到"主"上下文)
我在iOS 4.3上使用基于SQLite的数据存储.
正在编写的记录确实有索引.
整个同步作业在单个GCD后台线程上处理(即dispatch_queue_create()和dispatch_async()).
我不知道为什么性能突然下降,或者可以采取什么措施来解决它.我已经四处寻找并阅读以下内容,但我还没有突然出现:
任何想法或指针使这个应用程序在数据库中扩展到100,000个记录将非常感激.
这个Instruments图表显示了与上面相同的模拟(在iPad2上),但包括磁盘活动统计数据,你可以清楚地看到所有"不在100%CPU运行"的时间似乎都被写入磁盘.

我还在iOS模拟器上运行了相同的同步尝试.除了包含随时间略微增长的对象ID的字典外,每个块的总内存使用量或多或少是恒定的(但这些不是CoreData对象或任何会影响保存的东西,它们只是NSNumbers).与总堆相比,此dict是少量内存,因此问题不会耗尽内存.
这个测试的有趣之处在于CoreData Save仪器报告连续保存花费的时间大致相同,这显然与第一组结果中的CPU分析信息冲突.似乎CoreData认为将更改推送到数据库需要花费相同的时间,但数据库本身(即SQLite)突然需要更长的时间才能将这些更改实际流式传输到磁盘.
performance scalability core-data nsmanagedobjectcontext ios
是否可以找到保存后在托管对象上保存的属性?例如,我有人在监听托管对象上下文保存(NSManagedObjectContextDidSaveNotification),我想知道对象的哪些属性已保存.
core-data objective-c nsmanagedobject nsmanagedobjectcontext
当我尝试保存CoreData模型的上下文时,收到错误
Unresolved error Error Domain=NSCocoaErrorDomain Code=1560 "The operation couldn’t be completed. (Cocoa error 1560.)" UserInfo=0x76924b0 {NSDetailedErrors=(
"Error Domain=NSCocoaErrorDomain Code=1570 "
The operation couldn\U2019t be completed. (Cocoa error 1570.)"
UserInfo=0x768c410 {NSValidationErrorObject=<Posts: 0x7177990> (entity: Posts; id: 0x7177010 <x-coredata:///Posts/tEF7138E6-A968-45B7-95CF-116C2AA93D605> ; data: {\n "
business_entity"
= nil;\n "
created_at"
= "
2012-01-21 03:31:30 +0000"
;\n "
own_description"
= "
Roasted this morning- Panama Duncan Estate: A rose fragrance debuts flavors of pear, coconut and marshmallow with caramel throughout the cup."
;\n postsID = 4;\n …
使用NSPrivateQueueConcurrencyType和NSMainQueueConcurrencyType类型时NSManagedObjectContext,在同一个上下文中进行嵌套的performBlock调用是否安全?
[backgroundContext performBlock:^{
NSFetchRequest *myRequest = ...;
__block NSArray *result= nil;
[backgroundContext performBlockAndWait:^{
results = [backgroundContext executeFetchRequest:myRequest error:NULL];
}];
}];
Run Code Online (Sandbox Code Playgroud)
它可能看起来很愚蠢但我有一个现有的代码库,其中包含很多帮助方法来封装executeFetchRequest调用.我不想假设调用者是否已经使用了performBlock.例如:
-(void)updateObjects:(BOOL)synchronous
{
if (YES == synchronous)
[self fetchHelper];
else
{
[backgroundContext performBlock:^{
[self fetchHelper];
}];
}
}
-(NSArray*)fetchHelper
{
[self.backgroundContext performBlockAndWait:^{
//Fetch the objects...
[self.backgroundContext executeFetchRequest: (...)];
}];
}
Run Code Online (Sandbox Code Playgroud)
我试过了它,它的工作原理.但我已经学会了(艰难的方式)对核心数据和多线程非常小心.
这方面有很多主题,但我还没有找到适用于Swift(Xcode 6.2)的解决方案.
为了在Swift中测试Core Data支持的类,我生成了新的托管对象上下文,然后我将其注入到我的类中.
//Given
let testManagedObjectContext = CoreDataTestComposer.setUpInMemoryManagedObjectContext()
let testItems = createFixtureData(testManagedObjectContext) as [TestItem]
self.itemDateCoordinator.managedObjectContext = testManagedObjectContext
//When
let data = self.itemDateCoordinator.do()
//Then
XCTAssert(data.exists)
Run Code Online (Sandbox Code Playgroud)
问题来自于将在Test中创建的MOC传递给正在进行的类.因为实体类是命名空间的,所以Core Data不会获取适当的ManagedObject子类,而是返回一个NSManagedObject集合.循环或对这些对象做任何事情时(在您的类中将是一个测试项目数组([TestItem]).
例如,违规类ItemDateCoordinator将执行此循环(在从a中提取相关数据之后NSFetchRequest)"
for testItem in testItems {
testItem.doPart(numberOfDays: 10)
}
Run Code Online (Sandbox Code Playgroud)
会导致:
致命错误:NSArray元素无法匹配Swift数组元素类型
此外,我遇到了一系列信息,没有太多可靠的答案:
我正在使用私有托管对象上下文来创建一些新对象到持久性存储中,然后在保存私有MOC之后,使用它们将它们合并到主MOC中mergeChangesFromContextDidSaveNotification.这工作正常,并根据需要更新UI,并且NSManagedObjectContextWillSaveNotification不会在此处调用mainMOC.
然后我对mainMOC使用UI 进行了一些更改,并听取了NSManagedObjectContextWillSaveNotification.通知已发布,但它不仅包含我所做的编辑,还包含从PrivateMOC使用中合并的对象mergeChangesFromContextDidSaveNotification.
有没有办法mainContext在后续contextDidChange通知中忽略从另一个上下文合并到的更改?
这是设置:
- (void) loadData {
privateContext = [[NSManagedObjectContext alloc] initWithConcurrencyType: NSPrivateQueueConcurrencyType];
privateContext.persistentStoreCoordinator = self.mainContext.persistentStoreCoordinator;
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(contextWillSave:)
name:NSManagedObjectContextWillSaveNotification
object: self.mainContext];
NSManagedObject *object = [NSEntityDescription insertNewObjectForEntityForName:record.recordType inManagedObjectContext: self.privateContext];
// fill in object
if ([self.privateContext hasChanges]) {
[self savePrivateContextAndMergeWithMainContext: self.privateContext];
}
}
- (void) savePrivateContextAndMergeWithMainContext: (NSManagedObjectContext *) privateContext {
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(privateContextDidChange:) name:NSManagedObjectContextDidSaveNotification object:privateContext];
__block NSError *error = …Run Code Online (Sandbox Code Playgroud) 堆栈溢出中已经有一个类似的问题,但是对我来说不起作用。
我的应用程序中有一个用例,其中我必须观察数据库的更改以执行某些操作。为了接收更新,我订阅了 NSManagedObjectContextObjectsDidChange通知(针对ViewContext),并且我也将其打开automaticallyMergesChangesFromParent。
但是,如果我update或delete某个对象在其他上下文上(使用newBackgroundContext()),则我不会收到对象发生更改通知,但它对于inserting新对象而言效果很好。
有人可以指导我为什么它仅对插入有效,即使启用后也不对更新和删除有效automaticallyMergesChangesFromParent吗?如果是实际行为,是否还有其他方法可以解决我的用例?
的文档(在中NSManagedObjectContext.h).automaticallyMergesChangesFromParent说:
上下文是否自动合并保存到其协调者或父上下文的更改。不支持将上下文固定到非当前查询生成时将此属性设置为YES。
我尝试了什么
NSFetchResultController它的正常工作测试了同一件事,但不幸的是,NSFetchResultController由于使用自定义视图来表示数据,因此无法使用privateQueueConcurrencyType上下文并将其设置viewContext为父级,并且令人惊讶地开始工作,因此问题仅在使用时出现,newBackgroundContext()但根据文档,它应该正常工作,因为两者都使用相同NSPersistentStoreCoordinator提前致谢!
core-data nsmanagedobject nsmanagedobjectcontext ios nspersistentcontainer
core-data ×10
ios ×7
ios5 ×2
iphone ×2
objective-c ×1
performance ×1
scalability ×1
swift ×1
xcode4 ×1