- objective-c - iOS 5 : Can you override UIAppearance customisations in specific classes?
- iphone - 如何将 CGFontRef 转换为 UIFont?
- ios - 以编程方式关闭标记的信息窗口 google maps iOS
- ios - Xcode 5 - 尝试验证存档时出现 "No application records were found"
我已经能够在我的应用程序中确认这一点,并且我创建了一个快速示例应用程序来确认这一点。这是设置:
您有两个托管对象上下文:
masterMOC: NSPrivateQueueConcurrencyType, tied to persistent store coordinator
mainMOC: NSMainQueueConcurrencyType, child of masterMOC, NOT tied to any store coordinator
这个设置的灵感来自 WWDC 视频,它建议我们可以通过将 masterMOC
设置为私有(private)队列并将其绑定(bind)到持久存储来节省后台线程。如果您使用 mainMOC
设置一个 NSFetchedResultsController
(它必须是 mainMOC
,因为它与 UI 绑定(bind)),并设置一个fetchBatchSize
,批量大小被忽略,所有实体立即出错。我启用了 SQLite 调试注释,当滚动浏览数千行(批处理大小为 20)时,没有触发任何错误。
如果我做一个简单的调整,即将持久存储协调器绑定(bind)到 mainMOC
并使其成为根上下文(也就是说,它不再是 master 的子级),那么批量大小完美运行,当我滚动浏览数千行时,触发了几个错误。
这是预期的行为吗?我错过了什么吗?
您可以下载示例项目here
最佳答案
文档中对嵌套上下文的讨论有限,它只出现在“Core Data Release Notes for iOS v5.0”和 UIManagedDocument
中。关于获取和嵌套上下文的唯一评论是:
fetch and save operations are mediated by the parent context instead of a coordinator.
鉴于缺少与使用嵌套上下文进行批量获取的功能相关的任何免责声明,我建议批量获取和嵌套上下文不兼容是不可能的。然而,这似乎是最基本的例子不起作用的情况。 (参见下面的测试代码)。
这里还有一个描述相同问题的公开雷达提交:http://openradar.appspot.com/11235622 ,以及 FetchedResultsControllers 和嵌套上下文中提到的其他问题:Duplication of entity when change made by a child ManagedObjectContext is pushed (saved) to its parent .
一个可能的部分解决方案是将 NSMainQueueConcurrencyType
的附加 NSManagedObjectContext
直接添加到相同的 NSPersistentStoreCoordinator
,其唯一目的是为 NSFetchedResultsController
。然后,当用户选择项目时,可以将 ObjectID 交还给嵌套子上下文,然后可以在嵌套上下文中执行任何后续编辑。
这显然会降低使用嵌套上下文的好处,并且需要更频繁地保存以在嵌套上下文和 NSFetchedResultsControllers
上下文之间进行同步。然而,根据应用程序的设计以及嵌套上下文与批量加载的相对优势,这可能会有用。 (参见下面的示例代码)
测试代码显示在嵌套上下文中最简单的批量获取失败:
#import "AppDelegate.h"
// Xcode 4.3.3:
// Create a new iOS Master-Detail project called "BatchTest" tick the "Use Core Data" check box.
// Delete all files except the AppDelegate and the BatchTest data model (leave supporting files).
// Delete all properties and methods from AppDelegate.h
// Paste this code into AppDelegate.m
// Switch on core data debugging by editing the "BatchTest" scheme and adding
// -com.apple.CoreData.SQLDebug 1
// To the "arguments passed on launch" list in the "Run" step
// Run.
@implementation AppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
/////////////////////////////////////////////////////////////////////////////////////
// Setup the core data stack.
/////////////////////////////////////////////////////////////////////////////////////
NSURL *modelURL = [[NSBundle mainBundle] URLForResource:@"BatchTest" withExtension:@"momd"];
NSManagedObjectModel *model = [[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL];
NSURL *appDocsDirectory = [[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] lastObject];
NSURL *storeURL = [appDocsDirectory URLByAppendingPathComponent:@"BatchTest.sqlite"];
NSPersistentStoreCoordinator *coordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:model];
[coordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeURL options:nil error:nil];
NSManagedObjectContext *parentContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
parentContext.persistentStoreCoordinator = coordinator;
NSManagedObjectContext *childContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType];
childContext.parentContext = parentContext;
/////////////////////////////////////////////////////////////////////////////////////
// Load some test data and reset the context.
/////////////////////////////////////////////////////////////////////////////////////
[parentContext performBlockAndWait:^{
for (int i=0; i<1000; i++) {
[NSEntityDescription insertNewObjectForEntityForName:@"Event" inManagedObjectContext:parentContext];
}
[parentContext save:nil];
[parentContext reset];
}];
/////////////////////////////////////////////////////////////////////////////////////
// Test Batched Fetching
/////////////////////////////////////////////////////////////////////////////////////
NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:@"Event"];
request.fetchBatchSize = 10;
// Fetch from the child.
NSArray *results = [childContext executeFetchRequest:request error:nil];
NSLog(@"Object 500: %@", [results objectAtIndex:500]);
// Result is all 1000 rows fetched in full, no subsequent batch fetching for event 500.
[childContext reset];
[parentContext performBlockAndWait:^{
[parentContext reset];
// Fetch from the parent.
NSArray *results = [parentContext executeFetchRequest:request error:nil];
NSLog(@"Object 500: %@", [results objectAtIndex:500]);
// Result is 1000 primary keys fetched, followed by a batch of 10 rows to find event 500.
}];
return YES;
}
@end
示例代码显示了使用附加上下文来为 NSFetchedResultsController
提供批处理工作:
#import "AppDelegate.h"
// Xcode 4.3.3:
// Create a new iOS Master-Detail project called "BatchTest" tick the "Use Core Data" check box.
// Delete all files except the AppDelegate and the BatchTest data model (leave supporting files).
// Delete all properties and methods from AppDelegate.h
// Paste this code into AppDelegate.m
// Switch on core data debugging by editing the "BatchTest" scheme and adding
// -com.apple.CoreData.SQLDebug 1
// To the "arguments passed on launch" list in the "Run" step
// Run.
@interface AppDelegate () {
NSManagedObjectContext *backgroundContext;
NSManagedObjectContext *editingContext;
NSManagedObjectContext *fetchedResultsControllerContext;
NSManagedObject *selectedObject;
}
@end
@implementation AppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
/////////////////////////////////////////////////////////////////////////////////////
// Setup the core data stack.
/////////////////////////////////////////////////////////////////////////////////////
NSURL *modelURL = [[NSBundle mainBundle] URLForResource:@"BatchTest" withExtension:@"momd"];
NSManagedObjectModel *model = [[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL];
NSURL *appDocsDirectory = [[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] lastObject];
NSURL *storeURL = [appDocsDirectory URLByAppendingPathComponent:@"BatchTest.sqlite"];
NSPersistentStoreCoordinator *coordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:model];
[coordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeURL options:nil error:nil];
backgroundContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
backgroundContext.persistentStoreCoordinator = coordinator;
editingContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType];
editingContext.parentContext = backgroundContext;
fetchedResultsControllerContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType];
fetchedResultsControllerContext.persistentStoreCoordinator = coordinator;
/////////////////////////////////////////////////////////////////////////////////////
// Load some test data and reset the context.
/////////////////////////////////////////////////////////////////////////////////////
[backgroundContext performBlockAndWait:^{
for (int i=0; i<1000; i++) {
[NSEntityDescription insertNewObjectForEntityForName:@"Event" inManagedObjectContext:backgroundContext];
}
[backgroundContext save:nil];
[backgroundContext reset];
}];
/////////////////////////////////////////////////////////////////////////////////////
// Example of three contexts performing different roles.
/////////////////////////////////////////////////////////////////////////////////////
// The fetchedResultsControllerContext will batch correctly as it is tied directly
// to the persistent store. It can be used to drive the UI as it is a Main Queue context.
NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:@"Event"];
request.fetchBatchSize = 10;
NSArray *fetchResults = [fetchedResultsControllerContext executeFetchRequest:request error:nil];
// User selects an object in the fetchedResultsControllerContext (i.e. in a UITableView).
selectedObject = [fetchResults lastObject];
NSLog(@"**** selectedObject.timeStamp before editing:%@", [selectedObject valueForKey:@"timeStamp"]);
// Pass the object to the editing context for editing using its objectID.
NSManagedObjectID *selectedObjectID = selectedObject.objectID;
NSManagedObject *objectForEditing = [editingContext objectWithID:selectedObjectID];
// Edit the object
[objectForEditing setValue:[NSDate date] forKey:@"timeStamp"];
// Subscribe to save notifications of the background context so the
// fetchedResultsControllerContext will be updated after the background save occurs.
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(backgroundContextDidSave:)
name:NSManagedObjectContextDidSaveNotification
object:backgroundContext];
// Save the editing context to push changes up to the parent, then background save.
[editingContext save:nil];
[backgroundContext performBlock:^{
[backgroundContext save:nil];
}];
return YES;
}
- (void)backgroundContextDidSave:(NSNotification *)notification {
[fetchedResultsControllerContext mergeChangesFromContextDidSaveNotification:notification];
NSLog(@"**** selectedObject.timeStamp after editing:%@", [selectedObject valueForKey:@"timeStamp"]);
// Merging changes into the fetchedResultsControllerContext would trigger updates
// to an NSFetchedResultsController and it's UITableView where these set up.
}
@end
关于iphone - 使用父/子上下文时批量大小不起作用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11365589/
出现以下错误 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])?只允许使用没有外部库的库,就像
我是一名优秀的程序员,十分优秀!