- 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"
保存
一个初始的NSManagedObjectContext
NSManagedObjectContext
设置一个 NSFetchedResultsController
,它根据 boolean
“显示”属性进行过滤。NSManagedObjectContext
上更新“show”并保存:
。我希望这会导致我的 NSFetchedResultsController
调用 NSFetchedResultsControllerDelegate
的 controllerDidChangeContent:
。我从来没有接到那个电话。 NSFetchedResultsController with predicate ignores changes merged from different NSManagedObjectContext的 accepted answer表示除了 controllerDidChangeContent:
,我还应该得到一个 NSManagedObjectContextObjectsDidChangeNotification
,但我也没有收到。
完整的代码示例包含在下面和 on github . I've filed a radar with Apple .
@interface HJBFoo : NSManagedObject
@property (nonatomic, retain) NSString *name;
@property (nonatomic, retain) NSNumber *show;
@end
@interface HJBAppDelegate () <NSFetchedResultsControllerDelegate>
@property (nonatomic, strong) NSPersistentStoreCoordinator *persistentStoreCoordinator;
@property (nonatomic, strong) NSManagedObjectContext *initialManagedObjectContext;
@property (nonatomic, strong) NSManagedObjectContext *fetchedResultsControllerManagedObjectContext;
@property (nonatomic, strong) NSFetchedResultsController *fetchedResultsController;
@end
@implementation HJBAppDelegate
#pragma mark - UIApplicationDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
self.window.backgroundColor = [UIColor whiteColor];
self.window.rootViewController = [UIViewController new];
NSAttributeDescription *nameAttributeDescription = [NSAttributeDescription new];
[nameAttributeDescription setAttributeType:NSStringAttributeType];
[nameAttributeDescription setIndexed:NO];
[nameAttributeDescription setOptional:NO];
[nameAttributeDescription setName:@"name"];
NSAttributeDescription *showAttributeDescription = [NSAttributeDescription new];
[showAttributeDescription setAttributeType:NSBooleanAttributeType];
[showAttributeDescription setIndexed:YES];
[showAttributeDescription setOptional:NO];
[showAttributeDescription setName:@"show"];
NSEntityDescription *fooEntityDescription = [NSEntityDescription new];
[fooEntityDescription setManagedObjectClassName:@"HJBFoo"];
[fooEntityDescription setName:@"HJBFoo"];
[fooEntityDescription setProperties:@[
nameAttributeDescription,
showAttributeDescription,
]];
NSManagedObjectModel *managedObjectModel = [NSManagedObjectModel new];
[managedObjectModel setEntities:@[
fooEntityDescription,
]];
self.persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:managedObjectModel];
NSError *error = nil;
if ([self.persistentStoreCoordinator addPersistentStoreWithType:NSInMemoryStoreType
configuration:nil
URL:nil
options:nil
error:&error]) {
self.initialManagedObjectContext = [NSManagedObjectContext new];
[self.initialManagedObjectContext setPersistentStoreCoordinator:self.persistentStoreCoordinator];
HJBFoo *foo1 = [NSEntityDescription insertNewObjectForEntityForName:@"HJBFoo"
inManagedObjectContext:self.initialManagedObjectContext];
foo1.name = @"1";
foo1.show = @YES;
HJBFoo *foo2 = [NSEntityDescription insertNewObjectForEntityForName:@"HJBFoo"
inManagedObjectContext:self.initialManagedObjectContext];
foo2.name = @"2";
foo2.show = @NO;
error = nil;
if ([self.initialManagedObjectContext save:&error]) {
NSFetchRequest *fetchRequest = [NSFetchRequest fetchRequestWithEntityName:@"HJBFoo"];
[fetchRequest setReturnsObjectsAsFaults:NO];
error = nil;
NSArray *initialFoos = [self.initialManagedObjectContext executeFetchRequest:fetchRequest
error:&error];
if (initialFoos) {
NSLog(@"Initial: %@", initialFoos);
self.fetchedResultsControllerManagedObjectContext = [NSManagedObjectContext new];
[self.fetchedResultsControllerManagedObjectContext setPersistentStoreCoordinator:self.persistentStoreCoordinator];
NSFetchRequest *shownFetchRequest = [NSFetchRequest fetchRequestWithEntityName:@"HJBFoo"];
[shownFetchRequest setPredicate:[NSPredicate predicateWithFormat:@"show == YES"]];
[shownFetchRequest setSortDescriptors:@[
[NSSortDescriptor sortDescriptorWithKey:@"name"
ascending:YES],
]];
self.fetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:shownFetchRequest
managedObjectContext:self.fetchedResultsControllerManagedObjectContext
sectionNameKeyPath:nil
cacheName:nil];
self.fetchedResultsController.delegate = self;
error = nil;
if ([self.fetchedResultsController performFetch:&error]) {
NSLog(@"Initial fetchedObjects: %@", [self.fetchedResultsController fetchedObjects]);
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(managedObjectContextDidSave:)
name:NSManagedObjectContextDidSaveNotification
object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(managedObjectContext2ObjectsDidChange:)
name:NSManagedObjectContextObjectsDidChangeNotification
object:self.fetchedResultsControllerManagedObjectContext];
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 0.5 * NSEC_PER_SEC),
dispatch_get_main_queue(),
^(void){
NSManagedObjectContext *managedObjectContext3 = [NSManagedObjectContext new];
[managedObjectContext3 setPersistentStoreCoordinator:self.persistentStoreCoordinator];
NSFetchRequest *foo2FetchRequest = [NSFetchRequest fetchRequestWithEntityName:@"HJBFoo"];
[foo2FetchRequest setFetchLimit:1];
[foo2FetchRequest setPredicate:[NSPredicate predicateWithFormat:@"name == %@",
@"2"]];
NSError *editingError = nil;
NSArray *editingFoos = [managedObjectContext3 executeFetchRequest:foo2FetchRequest
error:&editingError];
if (editingFoos) {
HJBFoo *editingFoo2 = [editingFoos objectAtIndex:0];
editingFoo2.show = @YES;
editingError = nil;
if ([managedObjectContext3 save:&editingError]) {
NSLog(@"Save succeeded. Expected (in order) managedObjectContextDidSave, controllerDidChangeContent, managedObjectContext2ObjectsDidChange");
} else {
NSLog(@"Editing save failed: %@ %@", [error localizedDescription], [error userInfo]);
}
} else {
NSLog(@"Editing fetch failed: %@ %@", [error localizedDescription], [error userInfo]);
}
});
} else {
NSLog(@"Failed initial fetch: %@ %@", [error localizedDescription], [error userInfo]);
}
} else {
NSLog(@"Failed to performFetch: %@ %@", [error localizedDescription], [error userInfo]);
}
} else {
NSLog(@"Failed to save initial state: %@ %@", [error localizedDescription], [error userInfo]);
}
} else {
NSLog(@"Failed to add persistent store: %@ %@", [error localizedDescription], [error userInfo]);
}
[self.window makeKeyAndVisible];
return YES;
}
#pragma mark - NSFetchedResultsControllerDelegate
- (void)controllerDidChangeContent:(NSFetchedResultsController *)controller {
NSLog(@"controllerDidChangeContent: %@",
[self.fetchedResultsController fetchedObjects]);
}
#pragma mark - notifications
- (void)managedObjectContextDidSave:(NSNotification *)notification {
NSManagedObjectContext *managedObjectContext = [notification object];
if (([managedObjectContext persistentStoreCoordinator] == self.persistentStoreCoordinator) &&
(managedObjectContext != self.fetchedResultsControllerManagedObjectContext)) {
NSLog(@"managedObjectContextDidSave: %@", notification);
[self.fetchedResultsControllerManagedObjectContext mergeChangesFromContextDidSaveNotification:notification];
}
}
- (void)managedObjectContext2ObjectsDidChange:(NSNotification *)notification {
NSLog(@"managedObjectContext2ObjectsDidChange: %@", notification);
}
@end
@implementation HJBFoo
@dynamic name;
@dynamic show;
@end
最佳答案
在我看来,应用来自 NSFetchedResultsController with predicate ignores changes merged from different NSManagedObjectContext 的修复/解决方法也可以解决您的问题。您的 managedObjectContextDidSave
方法将如下所示:
- (void)managedObjectContextDidSave:(NSNotification *)notification {
NSManagedObjectContext *managedObjectContext = [notification object];
if (([managedObjectContext persistentStoreCoordinator] == self.persistentStoreCoordinator) &&
(managedObjectContext != self.fetchedResultsControllerManagedObjectContext)) {
NSLog(@"managedObjectContextDidSave: %@", notification);
// Fix/workaround from https://stackoverflow.com/questions/3923826/nsfetchedresultscontroller-with-predicate-ignores-changes-merged-from-different/3927811#3927811
for(NSManagedObject *object in [[notification userInfo] objectForKey:NSUpdatedObjectsKey]) {
[[self.fetchedResultsControllerManagedObjectContext objectWithID:[object objectID]] willAccessValueForKey:nil];
}
[self.fetchedResultsControllerManagedObjectContext mergeChangesFromContextDidSaveNotification:notification];
}
}
并且 NSLog 输出看起来符合预期:
Initial: (
"<HJBFoo: 0xaa19670> (entity: HJBFoo; id: 0xaa1afd0 <x-coredata://07E97098-E32D-45F6-9AB4-F9DAB9B0AC1A/HJBFoo/p2> ; data: {\n name = 1;\n show = 1;\n})",
"<HJBFoo: 0xaa1a200> (entity: HJBFoo; id: 0xaa1af50 <x-coredata://07E97098-E32D-45F6-9AB4-F9DAB9B0AC1A/HJBFoo/p1> ; data: {\n name = 2;\n show = 0;\n})"
)
Initial fetchedObjects: (
"<HJBFoo: 0x74613f0> (entity: HJBFoo; id: 0xaa1afd0 <x-coredata://07E97098-E32D-45F6-9AB4-F9DAB9B0AC1A/HJBFoo/p2> ; data: <fault>)"
)
managedObjectContextDidSave: NSConcreteNotification 0xaa1f480 {name = NSManagingContextDidSaveChangesNotification; object = <NSManagedObjectContext: 0xaa1ed90>; userInfo = {
inserted = "{(\n)}";
updated = "{(\n <HJBFoo: 0xaa1f2d0> (entity: HJBFoo; id: 0xaa1af50 <x-coredata://07E97098-E32D-45F6-9AB4-F9DAB9B0AC1A/HJBFoo/p1> ; data: {\n name = 2;\n show = 1;\n})\n)}";
}}
Save succeeded. Expected (in order) managedObjectContextDidSave, controllerDidChangeContent, managedObjectContext2ObjectsDidChange
controllerDidChangeContent: (
"<HJBFoo: 0x74613f0> (entity: HJBFoo; id: 0xaa1afd0 <x-coredata://07E97098-E32D-45F6-9AB4-F9DAB9B0AC1A/HJBFoo/p2> ; data: {\n name = 1;\n show = 1;\n})",
"<HJBFoo: 0xaa1f9c0> (entity: HJBFoo; id: 0xaa1af50 <x-coredata://07E97098-E32D-45F6-9AB4-F9DAB9B0AC1A/HJBFoo/p1> ; data: {\n name = 2;\n show = 1;\n})"
)
managedObjectContext2ObjectsDidChange: NSConcreteNotification 0xaa1fbb0 {name = NSObjectsChangedInManagingContextNotification; object = <NSManagedObjectContext: 0x745fa50>; userInfo = {
managedObjectContext = "<NSManagedObjectContext: 0x745fa50>";
refreshed = "{(\n <HJBFoo: 0xaa1f9c0> (entity: HJBFoo; id: 0xaa1af50 <x-coredata://07E97098-E32D-45F6-9AB4-F9DAB9B0AC1A/HJBFoo/p1> ; data: {\n name = 2;\n show = 1;\n})\n)}";
}}
所以会发生以下事情:
managedObjectContext3
中进行更改并保存。NSManagedObjectContextDidSaveNotification
并且 managedObjectContextDidSave:
被调用。此通知包含在后台上下文中更新的对象。打电话
[self.fetchedResultsControllerManagedObjectContext mergeChangesFromContextDidSaveNotification:notification];
现在不会做任何事情,因为更新的对象还没有加载到fetchedResultsControllerManagedObjectContext
中或者是一个错误。特别是,此上下文不会发布 NSManagedObjectContextObjectsDidChangeNotification
并且获取的结果 Controller 不会更新。
willAccessValueForKey
会首先强制 fetchedResultsControllerManagedObjectContext
加载这些对象并触发错误。打电话
[self.fetchedResultsControllerManagedObjectContext mergeChangesFromContextDidSaveNotification:notification];
之后实际更新 fetchedResultsControllerManagedObjectContext
中的对象。
NSManagedObjectContextObjectsDidChangeNotification
,并且获取的结果 Controller 调用相应的委托(delegate)函数。关于objective-c - NSFetchedResultsController 不调用 controllerDidChangeContent : after update to non-fetched NSManagedObject,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14018068/
您好,我现在遇到以下错误。 CoreData: error: Serious application error. An exception was caught from the delegate
我的应用程序非常简单:一个 TableViewController 显示存储在 Core Data 中的内容。添加按钮以模态方式推送第二个 View ,这使我可以将内容保存到 Core Data 中。
我目前的设置: 我打算使用 UISegmentedControl 在我想在表格 View 中显示的数据之间切换。 我一直在使用 restkit 进行与 web 服务的所有安静交互。数据存储在 core
我在实现一个非常基本的 NSFetchedResultsController 时遇到了问题。我有以下 super 简单的演示应用程序,只设置了一个 View 和一个按钮,CoreData 堆栈实现是由
我有 UITableViewController 表并使用 NSFetchedResultsController 从核心数据中获取行。我的 tableView 负责分层数据。每个行位置代表层(在零行最
我正在为 iOS 6.1 编写代码并学习如何使用 Core Data。 fetchedObjects 的文档说: “结果数组反射(reflect)了 Controller 的托管对象上下文中托管对象的
在类似的线程之前开始,但我现在知道问题出在哪里,所以我正在为您缩小范围: 我有两个 View Controller 。第一个叫做 MainCategoriesViewController,第二个是 N
我有一个包含两个托管对象上下文的应用程序: @property (nonatomic, strong) NSManagedObjectContext *managedObjectContext; @p
我正在尝试在 UITableView 中使用 NSFetchedResultsController。但是由于某些原因,当我添加一个新条目时,NSFetchedResultsControllerDele
我有一个后台线程执行后台更新,设置/覆盖几种 NSManagedObjects 上的字段。所有子类都包含一个 lastModified 属性,该属性在被后台任务处理时始终得到更新。 我的问题是,当我这
这是我的全部NSFetchedResultsControllerDelegate: //MARK: - NSFetchedResultsControllerDelegate func controll
我正在开发一个涉及可折叠部分的核心数据应用程序。 基本上,如果我跨部分移动托管对象,或者只是在其部分打开时将其删除,我会收到以下错误: 2014-04-28 19:38:44.690 uRSS[663
在 Swift 的 iOS 开发中使用 NSFetchedResultsController 和核心数据是非常奇怪的情况。 起初,FetchedResultsController 仅包含未更改部分的信
我有以下委托(delegate),我需要测试是否调用了 tableView.beginUpdates()。我正在使用 XCTest 和 Swift 3。您有任何想法或示例代码吗? extension
当我在我的 TabbarController 和 Viewcontrollers 中的两个选项卡之间切换时,这两个选项卡都包含一个 NSFetchResultsController。在我的一个 Vie
我填充并保存一个初始的NSManagedObjectContext 使用不同的 NSManagedObjectContext 设置一个 NSFetchedResultsController,它根据 b
我在我的应用程序中使用核心数据,但我注意到它有点慢,而且我遇到了一些不一致问题的崩溃,也许我管理不善,但我想传递给 SQLite 并且我找到了 FMDB 库,但我的问题是当我在数据库中进行后台更改时如
我是一名优秀的程序员,十分优秀!