使用父/子上下文时,批处理大小不起作用

时间:2022-09-17 21:51:46

I've been able to confirm this on my application, and a quick sample application I created to confirm this. Here's the setup:

我已经能够在我的应用程序上确认这一点,并且我创建了一个快速示例应用程序来确认这一点。这是设置:

You have two managed object contexts:

您有两个托管对象上下文:

masterMOC: NSPrivateQueueConcurrencyType, tied to persistent store coordinator
mainMOC: NSMainQueueConcurrencyType, child of masterMOC, NOT tied to any store coordinator

This setup was inspired from the WWDC video, which suggests we can save on a background thread by setting the masterMOC to a private queue and tie it to the persistent store. If you set up an NSFetchedResultsController using the mainMOC (and it must be the mainMOC since that's the one tied to the UI), and set a fetchBatchSize, the batch size is disregarded and all entities are faulted in at once. I enabled the SQLite debug annotations, and when scrolling through thousands of rows (with a batch size of 20), no faults are fired what so ever.

此设置的灵感来自WWDC视频,它建议我们可以通过将masterMOC设置为专用队列并将其绑定到持久存储来保存后台线程。如果使用mainMOC设置NSFetchedResultsController(并且它必须是mainMOC,因为它是绑定到UI的那个),并设置fetchBatchSize,则忽略批量大小,并且所有实体都会立即出现故障。我启用了SQLite调试注释,当滚动数千行(批量大小为20)时,没有任何错误被触发。

If I make one simple adjustment, namely tie the persistent store coordinator to the mainMOC and make it a root context (that is, it is no longer a child of master), then the batch size works perfectly, and as I scroll through thousands of rows, several faults are fired.

如果我进行一个简单的调整,即将持久存储协调器绑定到mainMOC并使其成为根上下文(即,它不再是master的子节点),那么批量大小完美地工作,并且当我滚动数千个行,几个故障被解雇。

Is this expected behavior? Am I missing something?

这是预期的行为吗?我错过了什么吗?

You can download the sample project here

您可以在此处下载示例项目

2 个解决方案

#1


6  

There is limited discussion of nested contexts in the documentation, it only appears in "Core Data Release Notes for iOS v5.0", and in UIManagedDocument. The only comment on fetching and nested contexts is:

文档中对嵌套上下文的讨论很有限,它只出现在“iOS v5.0的核心数据发行说明”和UIManagedDocument中。关于获取和嵌套上下文的唯一注释是:

fetch and save operations are mediated by the parent context instead of a coordinator.

获取和保存操作由父上下文而不是协调器调解。

Given the lack of any disclaimers relating to the functionality of batch fetching with nested contexts, I would suggest it is not expected that batch fetching and nested contexts are incompatible. However this seems to be the case as the most basic example does not function. (See test code below).

鉴于缺乏与嵌套上下文批量提取功能相关的任何免责声明,我建议不要求批量提取和嵌套上下文不兼容。然而,这似乎是这种情况,因为最基本的例子不起作用。 (参见下面的测试代码)。

There is also an open radar submission describing the same problem here: http://openradar.appspot.com/11235622, and other problems noted with FetchedResultsControllers and nested contexts: Duplication of entity when change made by a child ManagedObjectContext is pushed (saved) to its parent.

此处还有一个开放的雷达提交描述了同样的问题:http://openradar.appspot.com/11235622,以及FetchedResultsControllers和嵌套上下文中提到的其他问题:当推送(保存)子项ManagedObjectContext进行更改时实体的重复给它的父母。

A possible partial solution could be to add an additional NSManagedObjectContext of NSMainQueueConcurrencyType directly to the same NSPersistentStoreCoordinator for the sole purpose of serving the NSFetchedResultsController. ObjectIDs could then be handed back to the nested child context when the user selects items, and any subsequent editing can then be performed in the nested contexts.

可能的部分解决方案可能是将NSMainQueueConcurrencyType的其他NSManagedObjectContext直接添加到同一个NSPersistentStoreCoordinator,其唯一目的是为NSFetchedResultsController提供服务。然后,当用户选择项目时,可以将ObjectID交还给嵌套的子上下文,然后可以在嵌套的上下文中执行任何后续编辑。

This obviously reduces the benefit of using nested contexts and would require more frequent saving to synchronise between the nested contexts and the NSFetchedResultsControllers context. However depending on the design of the application and the relative benefits of nested contexts vs batch loading this may be useful. (See example code below)

这显然降低了使用嵌套上下文的好处,并且需要更频繁地保存以在嵌套上下文和NSFetchedResultsControllers上下文之间进行同步。但是,根据应用程序的设计以及嵌套上下文与批量加载的相对优势,这可能很有用。 (参见下面的示例代码)

Test code showing failure of simplest case batch fetching in nested contexts:

测试代码显示嵌套上下文中最简单的案例批量提取失败:

#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

Example code showing use of an additional context to serve an NSFetchedResultsController with batching working:

示例代码显示使用附加上下文来为具有批处理工作的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

#2


0  

From NSFetchRequest Class Reference:

来自NSFetchRequest类参考:

When the fetch is executed, the entire request is evaluated and the identities of all matching objects recorded, but no more than batchSize objects’ data will be fetched from the persistent store at a time. The array returned from executing the request will be a proxy object that transparently faults batches on demand.

执行提取时,将评估整个请求并记录所有匹配对象的标识,但一次只能从持久性存储中提取batchSize对象的数据。从执行请求返回的数组将是一个代理对象,可根据需要透明地对批处理进行故障处理。

So if the managed object context is not attached to a persistent store, there is nothing to fetch against - so the behavior you are seeing is at least somewhat consistent with the documentation. fetchLimit may work in the scenario you are describing. I would still fire a radar on it at bugreporter.apple.com .

因此,如果托管对象上下文未附加到持久性存储,则无需提取任何内容 - 因此您看到的行为至少与文档一致。 fetchLimit可能在您描述的场景中起作用。我仍然会在bugreporter.apple.com上发射雷达。

#1


6  

There is limited discussion of nested contexts in the documentation, it only appears in "Core Data Release Notes for iOS v5.0", and in UIManagedDocument. The only comment on fetching and nested contexts is:

文档中对嵌套上下文的讨论很有限,它只出现在“iOS v5.0的核心数据发行说明”和UIManagedDocument中。关于获取和嵌套上下文的唯一注释是:

fetch and save operations are mediated by the parent context instead of a coordinator.

获取和保存操作由父上下文而不是协调器调解。

Given the lack of any disclaimers relating to the functionality of batch fetching with nested contexts, I would suggest it is not expected that batch fetching and nested contexts are incompatible. However this seems to be the case as the most basic example does not function. (See test code below).

鉴于缺乏与嵌套上下文批量提取功能相关的任何免责声明,我建议不要求批量提取和嵌套上下文不兼容。然而,这似乎是这种情况,因为最基本的例子不起作用。 (参见下面的测试代码)。

There is also an open radar submission describing the same problem here: http://openradar.appspot.com/11235622, and other problems noted with FetchedResultsControllers and nested contexts: Duplication of entity when change made by a child ManagedObjectContext is pushed (saved) to its parent.

此处还有一个开放的雷达提交描述了同样的问题:http://openradar.appspot.com/11235622,以及FetchedResultsControllers和嵌套上下文中提到的其他问题:当推送(保存)子项ManagedObjectContext进行更改时实体的重复给它的父母。

A possible partial solution could be to add an additional NSManagedObjectContext of NSMainQueueConcurrencyType directly to the same NSPersistentStoreCoordinator for the sole purpose of serving the NSFetchedResultsController. ObjectIDs could then be handed back to the nested child context when the user selects items, and any subsequent editing can then be performed in the nested contexts.

可能的部分解决方案可能是将NSMainQueueConcurrencyType的其他NSManagedObjectContext直接添加到同一个NSPersistentStoreCoordinator,其唯一目的是为NSFetchedResultsController提供服务。然后,当用户选择项目时,可以将ObjectID交还给嵌套的子上下文,然后可以在嵌套的上下文中执行任何后续编辑。

This obviously reduces the benefit of using nested contexts and would require more frequent saving to synchronise between the nested contexts and the NSFetchedResultsControllers context. However depending on the design of the application and the relative benefits of nested contexts vs batch loading this may be useful. (See example code below)

这显然降低了使用嵌套上下文的好处,并且需要更频繁地保存以在嵌套上下文和NSFetchedResultsControllers上下文之间进行同步。但是,根据应用程序的设计以及嵌套上下文与批量加载的相对优势,这可能很有用。 (参见下面的示例代码)

Test code showing failure of simplest case batch fetching in nested contexts:

测试代码显示嵌套上下文中最简单的案例批量提取失败:

#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

Example code showing use of an additional context to serve an NSFetchedResultsController with batching working:

示例代码显示使用附加上下文来为具有批处理工作的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

#2


0  

From NSFetchRequest Class Reference:

来自NSFetchRequest类参考:

When the fetch is executed, the entire request is evaluated and the identities of all matching objects recorded, but no more than batchSize objects’ data will be fetched from the persistent store at a time. The array returned from executing the request will be a proxy object that transparently faults batches on demand.

执行提取时,将评估整个请求并记录所有匹配对象的标识,但一次只能从持久性存储中提取batchSize对象的数据。从执行请求返回的数组将是一个代理对象,可根据需要透明地对批处理进行故障处理。

So if the managed object context is not attached to a persistent store, there is nothing to fetch against - so the behavior you are seeing is at least somewhat consistent with the documentation. fetchLimit may work in the scenario you are describing. I would still fire a radar on it at bugreporter.apple.com .

因此,如果托管对象上下文未附加到持久性存储,则无需提取任何内容 - 因此您看到的行为至少与文档一致。 fetchLimit可能在您描述的场景中起作用。我仍然会在bugreporter.apple.com上发射雷达。