标签: nsmanagedobjectcontext

在iOS 5上实现快速高效的核心数据导入

问题:如何获取子上下文以查看父上下文中保留的更改,以便它们触发我的NSFetchedResultsController来更新UI?

这是设置:

你有一个下载并添加大量XML数据的应用程序(大约200万条记录,每条记录大致与正常段落的文本大小相同).sqlite文件的大小约为500 MB.将此内容添加到Core Data需要时间,但您希望用户能够在数据以递增方式加载到数据存储中时使用该应用程序.用户必须看不到大量数据被移动,因此没有挂起,没有抖动:滚动像黄油一样.尽管如此,该应用程序更有用,添加的数据越多,因此我们不能永远等待将数据添加到Core Data存储中.在代码中这意味着我真的想在导入代码中避免这样的代码:

[[NSRunLoop currentRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:0.25]];
Run Code Online (Sandbox Code Playgroud)

该应用仅限iOS 5,因此需要支持的最慢设备是iPhone 3GS.

以下是我目前用于开发当前解决方案的资源:

Apple的核心数据编程指南:高效导入数据

  • 使用自动释放池来降低内存
  • 关系成本.导入平面,然后在最后修补关系
  • 不要询问你是否可以帮助它,它会以O(n ^ 2)的方式减慢速度
  • 批量导入:保存,重置,排空和重复
  • 导入时关闭撤消管理器

iDeveloper TV - 核心数据性能

  • 使用3种上下文:Master,Main和Confinement上下文类型

iDeveloper TV - 适用于Mac,iPhone和iPad更新的核心数据

  • 使用performBlock在其他队列上运行保存会使事情变得更快.
  • 加密会减慢速度,如果可以,请将其关闭.

Marcus Zarra在核心数据中导入和显示大型数据集

  • 您可以通过为当前运行循环提供时间来减慢导入速度,因此用户感觉很顺利.
  • 示例代码证明可以执行大型导入并保持UI响应,但不能像使用3个上下文和异步保存到磁盘一样快.

我目前的解决方案

我有3个NSManagedObjectContext实例:

masterManagedObjectContext - 这是具有NSPersistentStoreCoordinator的上下文,负责保存到磁盘.我这样做,所以我的保存可以是异步的,因此非常快.我在发布时创建它,如下所示:

masterManagedObjectContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
[masterManagedObjectContext setPersistentStoreCoordinator:coordinator];
Run Code Online (Sandbox Code Playgroud)

mainManagedObjectContext - 这是UI在任何地方使用的上下文.它是masterManagedObjectContext的子代.我像这样创建它:

mainManagedObjectContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType];
[mainManagedObjectContext setUndoManager:nil];
[mainManagedObjectContext setParentContext:masterManagedObjectContext];
Run Code Online (Sandbox Code Playgroud)

backgroundContext - 此上下文在我的NSOperation子类中创建,该子类负责将XML数据导入Core Data.我在操作的main方法中创建它并将其链接到那里的主上下文.

backgroundContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSConfinementConcurrencyType];
[backgroundContext setUndoManager:nil];
[backgroundContext setParentContext:masterManagedObjectContext];
Run Code Online (Sandbox Code Playgroud)

这实际上非常非常快.只需通过这3个上下文设置,我就可以将导入速度提高10倍以上!老实说,这很难相信.(此基本设计应该是标准Core Data模板的一部分......)

在导入过程中,我保存了两种不同的方式.我在背景上下文中保存的每1000个项目:

BOOL saveSuccess …
Run Code Online (Sandbox Code Playgroud)

core-data nsfetchedresultscontroller nsmanagedobjectcontext ios

98
推荐指数
1
解决办法
1万
查看次数

核心数据背景上下文最佳实践

我需要对核心数据执行大量的导入任务.
假设我的核心数据模型如下所示:

Car
----
identifier 
type
Run Code Online (Sandbox Code Playgroud)

我从我的服务器获取汽车信息JSON列表,然后我想将它与我的核心数据Car对象同步,这意味着:
如果它是一辆新车 - > Car从新信息创建一个新的Core Data 对象.
如果汽车已经存在 - >更新Core Data Car对象.

所以我想在后台进行导入,而不会阻止UI,而使用滚动显示所有汽车的汽车表视图.

目前我正在做这样的事情:

// create background context
NSManagedObjectContext *bgContext = [[NSManagedObjectContext alloc]initWithConcurrencyType:NSPrivateQueueConcurrencyType];
[bgContext setParentContext:self.mainContext];

[bgContext performBlock:^{
    NSArray *newCarsInfo = [self fetchNewCarInfoFromServer]; 

    // import the new data to Core Data...
    // I'm trying to do an efficient import here,
    // with few fetches as I can, and in batches
    for (... num of batches ...) {

        // do batch import... …
Run Code Online (Sandbox Code Playgroud)

core-data objective-c nsmanagedobjectcontext ios

75
推荐指数
3
解决办法
3万
查看次数

什么是NSManagedObjectContext的performBlock:用于?

在iOS 5中,NSManagedObjectContext有几种新方法,performBlock:performBlockAndWait:.实际使用的这些方法是什么?它们在旧版本中取代了什么?什么样的街区应该传递给他们?我该如何决定使用哪个?如果有人有一些使用它们的例子,那就太好了.

core-data blocking nsmanagedobjectcontext ios ios5

67
推荐指数
1
解决办法
3万
查看次数

如何跟踪/观察子图中的所有更改?

我有一个NSManagedObjectContext,其中我有许多NSManagedObjects的子类,有些是其他人的容器.我想要做的是观察一个顶级对象,通知它对任何属性,关联或它包含的任何对象的属性/关联的任何更改.

使用上下文的'hasChanges'并没有给我足够的粒度.对象'isUpdated'方法仅适用于给定对象(而不是其关联中的任何对象).是否有一个方便的(也许是基于KVO的)我可以观察上下文中仅限于子图的变化?

iphone core-data nsmanagedobject nsmanagedobjectcontext

58
推荐指数
2
解决办法
2万
查看次数

如何将NSManagedObject从一个上下文复制或移动到另一个上下文?

我有一个相当标准的设置,一个从未保存的暂存器MOC(包含从Web下载的一堆对象)和另一个永久MOC持久化对象.当用户从scratchMOC中选择一个对象添加到她的库时,我想要1)从scratchMOC中删除对象并插入到permanentMOC中,或者2)将对象复制到permanentMOC中.该核心数据FAQ说,我可以复制的对象是这样的:

NSManagedObjectID *objectID = [managedObject objectID];
NSManagedObject *copy = [context2 objectWithID:objectID];
Run Code Online (Sandbox Code Playgroud)

(In this case, context2 would be permanentMOC.) However, when I do this, the copied object is faulted; the data is initially unresolved. When it does get resolved, later, all of the values are nil; none of the data (attributes or relationships) from the original managedObject are actually copied or referenced. Therefore I can't see any difference between using this objectWithID: method and just inserting an entirely new …

cocoa cocoa-touch core-data nsmanagedobject nsmanagedobjectcontext

53
推荐指数
3
解决办法
2万
查看次数

何时使用Core Data的NSMainQueueConcurrencyType?

正在初始化一个NSManagedObjectContext使用NSMainQueueConcurrencyType只为那MOC存在使用初始化的孩子MOC的情况NSPrivateQueueConcurrencyType

为了给出一些背景知识:我的应用程序具有传统结构,主表视图由a驱动NSFetchedResultsController,数据使用NSOperation具有自己MOC 的子类从Web服务异步导入.我不确定那种情况下的两个MOC是否应该使用NSConfinementConcurrencyType(默认情况下,我相信)或者是否应该使用NSMainQueueConcurrencyType与主线程上的获取结果控制器相关联的MOC 以及后台MOC应该使用的MOC NSConfinementConcurrencyType.

iphone cocoa-touch core-data nsmanagedobjectcontext ios

33
推荐指数
1
解决办法
1万
查看次数

CoreData无法解决问题

我有一个非常烦人的问题,我似乎无法修复.

我有一个视图,当我发送一条消息,保存到核心数据,当它完成时它向数据库询问随机消息(句子)并将其保存到数据库中的另一行.

如果我最后一部分硬编码,没有从数据库中获取数据,它可以正常工作,但是只要我从数据库中获取随机行就会发疯.

在我的AppDelegate.m中:

- (void)save {
    NSAssert(self.context != nil, @"Not initialized");
    NSError *error = nil;
    BOOL failed = [self.context hasChanges] && ![self.context save:&error];
    NSAssert1(!failed,@"Save failed %@",[error userInfo]);
}

- (NSString*)selectRandomSentence
{
    NSFetchRequest *request = [[NSFetchRequest alloc] init];
    NSEntityDescription *entity = [NSEntityDescription entityForName:@"Sentences" inManagedObjectContext:self.managedObjectContext];
    [request setEntity:entity];

    NSError *error = nil;
    NSUInteger count = [self.context countForFetchRequest:request error:&error];

    NSUInteger offset = count - (arc4random() % count);
    [request setFetchOffset:offset];
    [request setFetchLimit:1];

    NSArray *sentenceArray = [self.context executeFetchRequest:request error:&error];

    [request release];

    return [[sentenceArray objectAtIndex:0] sentence]; …
Run Code Online (Sandbox Code Playgroud)

core-data objective-c nsmanagedobject nsmanagedobjectcontext ios

33
推荐指数
2
解决办法
3万
查看次数

核心数据嵌套的托管对象上下文和频繁的死锁/冻结

我有一个问题几乎与此人描述的问题相同,但它没有得到答案:

http://www.cocoabuilder.com/archive/cocoa/312683-core-data-nested-managed-object-contexts-and-frequent-deadlocks.html#312683

这是问题所在:

我有一个使用NSPrivateQueueConcurrencyType和持久性存储协调器集的父MOC设置,它有一个带有NSMainQueueConcurrencyType的子MOC设置.大多数长期努力工作和保存的想法可以在私有MOC上完成,从而使主线程阻止UI.不幸的是,我似乎遇到了导致死锁的几种情况.

如果子MOC(在主线程上)正在使用NSFetchedResultsController执行提取,则会向父上下文发送-executeFetchRequest:它可以创建死锁.这两个操作都是在performBlock的上下文中完成的:对于它们各自的MOC,尽管文档似乎表明在没有performBlock的主线程上使用主线程并发类型MOC是好的.

看起来私有队列正在等待主线程上的子上下文已经锁定的PSC锁.看起来子上下文(在持有PSC锁定时)试图将dispatch_sync分配给父上下文,因此它们都在等待彼此.

是PriveQueue - > MainQueue是支持的配置吗?似乎大多数人仍然在主线程上有父上下文.

主线程看起来像这样:

> #0    0x960f6c5e in semaphore_wait_trap ()
> #1    0x04956bb5 in _dispatch_thread_semaphore_wait ()
> #2    0x04955c8f in _dispatch_barrier_sync_f_slow ()
> #3    0x04955dea in dispatch_barrier_sync_f ()
> #4    0x01797de5 in _perform ()
> #5    0x01798547 in -[NSManagedObjectContext(_NestedContextSupport) newValuesForObjectWithID:withContext:error:] ()
> #6    0x0176416b in _PFFaultHandlerLookupRow ()
> #7    0x01763f97 in -[NSFaultHandler fulfillFault:withContext:forIndex:] ()
> #8    0x01763b75 in _PF_FulfillDeferredFault ()
> #9    0x017639f2 in _sharedIMPL_pvfk_core ()
> #10    0x017681a0 in _pvfk_11 ()
> …
Run Code Online (Sandbox Code Playgroud)

core-data objective-c nsfetchedresultscontroller nsmanagedobjectcontext ios

30
推荐指数
1
解决办法
1万
查看次数

核心数据iOS10:viewContext没有使用NSFetchResultController从newBackgroundContext()接收更新

在我的应用程序中,我有一个NSFetchedResultsController在UITableView中加载Core Data对象.与此FRC关联的获取请求使用viewContext可用于NSPersistentContainer(iOS10)的新属性.

当我选择一个单元格时,我将Core Data对象传递给一个新的ViewController.这个新的VC仍然使用viewContext.从这个ViewController,我可以从模态呈现的ViewControllers更新Core Data对象.为此,我使用newBackgroundContext()模态ViewControllers.我可以毫无问题地保存更新Core Data对象.

问题是FRC不会使用后台上下文中的更新Core Data对象自动更新.就好像viewContext没有被接收并处理Core Data对象更新一样.

如果我automaticallyMergesChangesFromParent为viewContext(app wide)设置为true,则FRC在保存背景上下文时获取更新的Core Data对象.根据我的理解,viewContext应该自动管理数据的合并.该文档描述了viewContext:"此上下文配置为生成并自动使用来自其他上下文的保存通知."

你能说明如何使用NSFetchResultController处理不同的上下文吗?

core-data nsfetchedresultscontroller nsmanagedobjectcontext ios ios10

30
推荐指数
3
解决办法
4806
查看次数

核心数据:子上下文是否为新插入的对象获取永久的objectID?

我有一个应用程序有两个托管对象上下文设置如下:

  • 父上下文:NSPrivateQueueConcurrencyType,链接到持久性存储.
  • 主要上下文:NSMainQueueConcurrencyType,父上下文的子项.

当将新的托管对象插入主上下文时,我保存主上下文,然后保存父上下文,如下所示:

[context performBlockAndWait:^{
    NSError * error = nil;
    if (![context save: &error]) {
        NSLog(@"Core Data save error %@, %@", error, [error userInfo]);
    }
}];

[parentContext performBlock:^{
    NSError *error = nil;
    BOOL result = [parentContext save: &error];
    if ( ! result ) {
        NSLog( @"Core Data save error in parent context %@, %@", error, [error userInfo] );
    }
}];
Run Code Online (Sandbox Code Playgroud)

我的理解是,当首次创建管理对象时,它具有临时性objectID.然后保存主上下文,并且此对象及其临时ID将转到父上下文.然后保存父上下文.保存最后一个上下文后,objectID父上下文中的临时变换为永久变形objectID.

所以:

  • 永久对象ID是否会自动传播回主(子)上下文?
  • 当我强制获取对象永久ID时 [NSManagedObjectContext obtainPermanentIDsForObjects:error:],然后对应用程序进行后台处理,重新激活它,重新加载,使用主要上下文获取对象objectWithID:,并访问属性,我得到

    "CoreData无法解决......".

这种方法有什么问题?

concurrency nested core-data nsmanagedobjectcontext ios

29
推荐指数
2
解决办法
5766
查看次数