- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我有一项需要处理核心数据的大型导入任务。
假设我的核心数据模型如下所示:
Car
----
identifier
type
Car
对象,含义:
Car
来自新信息的对象。
Car
对象。
// 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...
// save bg context in the end of each batch
[bgContext save:&error];
}
// when all import batches are over I call save on the main context
// save
NSError *error = nil;
[self.mainContext save:&error];
}];
setParentContext
?
setParentContext
的例子。 ,相反,他们做这样的事情:
NSManagedObjectContext *bgContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
bgContext.persistentStoreCoordinator = self.mainContext.persistentStoreCoordinator;
bgContext.undoManager = nil;
[[NSNotificationCenter defaultCenter] addObserverForName:NSManagedObjectContextDidSaveNotification object:nil queue:nil usingBlock:^(NSNotification* note) {
NSManagedObjectContext *moc = self.managedObjectContext;
if (note.object != moc) {
[moc performBlock:^(){
[moc mergeChangesFromContextDidSaveNotification:note];
}];
}
}];
AppDelegate.m
#pragma mark - Core Data stack
- (void)saveContext {
NSError *error = nil;
NSManagedObjectContext *managedObjectContext = self.managedObjectContext;
if (managedObjectContext != nil) {
if ([managedObjectContext hasChanges] && ![managedObjectContext save:&error]) {
DDLogError(@"Unresolved error %@, %@", error, [error userInfo]);
abort();
}
}
}
// main
- (NSManagedObjectContext *)managedObjectContext {
if (_managedObjectContext != nil) {
return _managedObjectContext;
}
_managedObjectContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType];
_managedObjectContext.parentContext = [self saveManagedObjectContext];
return _managedObjectContext;
}
// save context, parent of main context
- (NSManagedObjectContext *)saveManagedObjectContext {
if (_writerManagedObjectContext != nil) {
return _writerManagedObjectContext;
}
NSPersistentStoreCoordinator *coordinator = [self persistentStoreCoordinator];
if (coordinator != nil) {
_writerManagedObjectContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
[_writerManagedObjectContext setPersistentStoreCoordinator:coordinator];
}
return _writerManagedObjectContext;
}
- (void)import {
NSManagedObjectContext *saveObjectContext = [AppDelegate saveManagedObjectContext];
// create background context
NSManagedObjectContext *bgContext = [[NSManagedObjectContext alloc]initWithConcurrencyType:NSPrivateQueueConcurrencyType];
bgContext.parentContext = saveObjectContext;
[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...
// save bg context in the end of each batch
[bgContext save:&error];
}
// no call here for main save...
// instead use NSManagedObjectContextDidSaveNotification to merge changes
}];
}
[[NSNotificationCenter defaultCenter] addObserverForName:NSManagedObjectContextDidSaveNotification object:nil queue:nil usingBlock:^(NSNotification* note) {
NSManagedObjectContext *mainContext = self.managedObjectContext;
NSManagedObjectContext *otherMoc = note.object;
if (otherMoc.persistentStoreCoordinator == mainContext.persistentStoreCoordinator) {
if (otherMoc != mainContext) {
[mainContext performBlock:^(){
[mainContext mergeChangesFromContextDidSaveNotification:note];
}];
}
}
}];
最佳答案
对于第一次接触 Core Data 的人来说,这是一个非常令人困惑的话题。我不是轻率地说,但根据经验,我有信心说 Apple 文档在这件事上有些误导(如果您仔细阅读它实际上是一致的,但它们并没有充分说明为什么合并数据仍然存在)在许多情况下,这是比依赖父/子上下文并简单地从子保存到父更好的解决方案)。
该文档给人一种强烈的印象,父/子上下文是进行后台处理的新首选方式。然而,苹果忽略了强调一些强烈的警告。首先,请注意,您在子上下文中获取的所有内容都是首先通过其父对象拉取的。因此,最好将在主线程上运行的主上下文的任何子级限制为处理(编辑)已经在主线程上的 UI 中呈现的数据。如果您将它用于一般同步任务,您很可能希望处理远远超出您当前在 UI 中显示的范围的数据。即使您使用 NSPrivateQueueConcurrencyType,对于子编辑上下文,您也可能会通过主上下文拖动大量数据,这可能会导致性能不佳和阻塞。现在最好不要让主上下文成为您用于同步的上下文的子级,因为除非您要手动执行同步更新,否则它不会收到同步更新的通知,而且您将在上下文您可能需要对作为级联启动的保存做出响应,该保存是从作为主要上下文的子级的编辑上下文,通过主要联系人并向下到数据存储的级联。您将不得不手动合并数据,也可能跟踪需要在主上下文中失效的内容并重新同步。不是最简单的模式。
Apple 文档没有明确说明的是,您最有可能需要将描述“旧”线程限制做事方式的页面上描述的技术与新的父子上下文做事方式混合使用。
您最好的选择可能是(我在这里给出了一个通用解决方案,最佳解决方案可能取决于您的详细要求),将 NSPrivateQueueConcurrencyType 保存上下文作为最顶层的父级,直接保存到数据存储区。 [编辑:你不会直接在这个上下文上做很多事情],然后给这个保存上下文至少两个直接子级。一个用于 UI 的 NSMainQueueConcurrencyType 主上下文 [编辑:最好遵守纪律并避免在此上下文中对数据进行任何编辑],另一个是 NSPrivateQueueConcurrencyType,用于对数据进行用户编辑以及(在附图中的选项 A)您的同步任务。
然后将主上下文作为同步上下文生成的 NSManagedObjectContextDidSave 通知的目标,并将通知 .userInfo 字典发送到主上下文的 mergeChangesFromContextDidSaveNotification:。
下一个要考虑的问题是将用户编辑上下文(用户所做的编辑反射(reflect)回界面的上下文)放在哪里。如果用户的操作始终仅限于对少量呈现数据的编辑,那么使用 NSPrivateQueueConcurrencyType 再次使其成为主上下文的子项是您最好的选择并且最容易管理(保存将直接将编辑保存到主上下文中,如果您有一个 NSFetchedResultsController,相应的委托(delegate)方法将被自动调用,以便您的 UI 可以处理更新 Controller :didChangeObject:atIndexPath:forChangeType:newIndexPath:)(这也是选项 A)。
另一方面,如果用户操作可能导致处理大量数据,您可能需要考虑使其成为主上下文和同步上下文的另一个对等体,以便保存上下文具有三个直接子级。 main、sync(私有(private)队列类型)和 edit(私有(private)队列类型)。我已经在图表中将这种安排显示为选项 B。
与同步上下文类似,您需要在保存数据时[编辑:配置主上下文以接收通知](或者如果您需要更多粒度,则在数据更新时)并采取措施合并数据(通常使用 mergeChangesFromContextDidSaveNotification: )。请注意,通过这种安排,主上下文不需要调用 save: 方法。
要了解父/子关系,请采取选项 A:父子方法仅意味着如果编辑上下文获取 NSManagedObjects,它们将首先“复制到”(注册到)保存上下文,然后是主上下文,最后是编辑上下文。您将能够对它们进行更改,然后当您调用 save: 在编辑上下文中时,更改将仅保存到主上下文中。您必须在主上下文上调用 save: 然后在将它们写出到磁盘之前在保存上下文上调用 save: 。
当您从子级保存到父级时,会触发各种 NSManagedObject 更改和保存通知。因此,例如,如果您使用 fetch results controller 来管理 UI 的数据,那么将调用它的委托(delegate)方法,以便您可以适本地更新 UI。
一些后果:如果您在编辑上下文中获取 object 和 NSManagedObject A,然后对其进行修改并保存,那么修改将返回到主上下文。您现在已针对主上下文和编辑上下文注册了修改后的对象。这样做会很糟糕,但是您现在可以在主上下文中再次修改对象,并且它现在将与存储在编辑上下文中的对象不同。如果您随后尝试对存储在编辑上下文中的对象进行进一步修改,您的修改将与主上下文中的对象不同步,并且任何保存编辑上下文的尝试都会引发错误。
出于这个原因,使用类似选项 A 的安排,尝试获取对象、修改它们、保存它们并重置编辑上下文(例如,[editContext reset] 与运行循环的任何单个迭代(或在传递给 [editContext performBlock:] 的任何给定块)也最好遵守纪律并避免对主上下文进行任何编辑。
此外,再重复一遍,由于 main 上的所有处理都是主线程,如果您将大量对象提取到编辑上下文,则主上下文将在主线程上进行提取处理,因为这些对象正在从父子上下文。如果正在处理大量数据,这可能会导致 UI 无响应。因此,例如,如果您有大量托管对象,并且您有一个 UI 选项可以使它们全部被编辑。在这种情况下,像选项 A 一样配置您的应用程序将是一个坏主意。在这种情况下,选项 B 是更好的选择。
如果您不处理数千个对象,则选项 A 可能完全足够。
顺便说一句,不要太担心您选择哪个选项。如果您需要更改为 B,从 A 开始可能是一个好主意。进行这样的更改比您想象的要容易,并且通常产生的后果比您预期的要少。
关于ios - 核心数据背景上下文最佳实践,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24657437/
出现以下错误 Network access for Distributed Transaction Manager (MSDTC) has been disabled. Please enable D
在调试应用程序时出现以下错误。 The CLR has been unable to transition from COM context 0x3b2d70 to COM context 0x3b2
在 GAE Go 中,为了记录,我们需要使用 appengine.NewContext(r) 创建一个新的上下文,它返回 context.Context。 如何使用此上下文在请求范围内设置/获取变量?
我想使用 Puppeteer 从放置在页面上 iframe 内的选择器中获取数据,该页面在与其父框架域不同的域上运行。因此,我不是任何域的所有者 - 无法使用 frame.postMessage。 试
我正在尝试获取可用的应用程序上下文并想切换到 webview 上下文,但 appium 仅获取 Navive App。 应用程序还启用了 WebView。 Appium 版本:1.10.1 Chrom
这个问题在这里已经有了答案: How to fix this nullOk error when using the flutter_svg package? (7 个回答) 7 个月前关闭。 当我尝
我观看了关于 Core Data 的 2016 WWDC 视频并查看了各种教程。我见过使用 Core Data Framework 创建对象以持久保存到 managedObjectContext 中的
这是代码 obj = { a: 'some value'; m: function(){ alert(this.a); } } obj.m(); 结果是'som
我正在尝试做类似的事情 $(".className").click(function() { $(this).(".anotherClass").css("z-index","1");
var User = { Name: "Some Name", Age: 26, Show: function() { alert("Age= "+this.Age)}; }; fun
我目前正在使用我见过的常见 Context 模式,它允许子组件通过传递修饰函数来更新父组件的状态(即 Provider)通过共享的 Context。 我遇到的问题是,修改函数只引用原始状态,不引用最新
有没有办法让 React Context类型安全与流类型? 例如: Button.contextTypes = { color: React.PropTypes.string }; 最佳答案 不幸
我想知道是否有一种方法可以为不同的功能使用不同的上下文类。 我希望有一个功能使用 MinkExtensions 进行浏览器测试,另一个功能使用和 HTTP 客户端(如 Guzzle)进行 API 测试
我有这个配置文件 apiVersion: v1 clusters: - cluster: server: [REDACTED] // IP of my cluster name: stag
我在实现非抢先式调度时遇到了用于初始化TCB的代码。 typedef struct TCB_t { struct TCB_t *next; struct TCB_t
我想将一个函数设置为数组中每个元素的属性,但使用不同的参数调用它。我想我会使用匿名函数来解决它: for ( var i = 0; i < object_count; i++ ) { obje
这个问题已经有答案了: How to access the correct `this` inside a callback (15 个回答) 已关闭 7 年前。 我正在做一些练习,但我在管道方法中丢
我正在尝试通过 Java 和 Android Studio 学习和制作 Android 应用程序。我对Java的了解程度是两年前几个小时的youtube学习和大学基础类(class)。不过我确实知道如
我在(这个)上遇到了问题。错误ImageView无法应用。我在 fragment 类中执行此代码。 ViewFlipper v_flipper; @Nullable @Override public
我想使用 openGL 的某些功能,但与渲染视觉内容无关。有没有办法在没有任何依赖性的情况下创建它(不是对 Windows,也不是某些包[SDL,SFML,GLUT])?只允许使用没有外部库的库,就像
我是一名优秀的程序员,十分优秀!