我一直遇到保存托管对象(在后台线程中)的问题,导致调用无法识别的选择器,这似乎与我处理NSManagedObjectContextObjectsDidChangeNotification
观察的方式有关。间歇性地,它将失败-[NSFetchRequest myManagedObjectContextDidChange:]: unrecognized selector sent to instance
。它并不总是NSFetchRequest
,有时它是NSKeyValueObservance
或未指定的,这让我相信观察者在托管对象被释放后仍然存在。
我将观察者添加到NSManagedObjectContextObjectsDidChangeNotification
并将其移除,如下所示。那有什么不对吗?
@interface Foo ()
@property (assign, nonatomic, getter = isObserving) BOOL observing;
@end
@implementation Foo
@synthesize observing = _observing;
- (void)awakeFromInsert {
[super awakeFromInsert];
self.addedDate = [NSDate date];
self.modificationDate = [self.addedDate copy];
[self commonAwake];
}
- (void)awakeFromFetch {
[super awakeFromFetch];
[self commonAwake];
}
- (void)awakeFromSnapshotEvents:(NSSnapshotEventType)flags {
[super awakeFromSnapshotEvents:flags];
[self commonAwake];
}
- (void)commonAwake
{
if (self.isObserving) return;
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(myManagedObjectContextDidChange:)
name:NSManagedObjectContextObjectsDidChangeNotification
object:self.managedObjectContext];
self.observing = YES;
}
- (void)willTurnIntoFault
{
[[NSNotificationCenter defaultCenter] removeObserver:self name:NSManagedObjectContextObjectsDidChangeNotification object:self.managedObjectContext];
self.observing = NO;
[super willTurnIntoFault];
}
- (void)myManagedObjectContextDidChange:(NSNotification*)notification {
NSDictionary *userInfo = [notification userInfo];
NSMutableSet *changedObjects = [NSMutableSet new];
NSSet *objects = nil;
objects = [userInfo objectForKey:NSInsertedObjectsKey];
[changedObjects unionSet:objects];
objects = [userInfo objectForKey:NSUpdatedObjectsKey];
[changedObjects unionSet:objects];
objects = [userInfo objectForKey:NSDeletedObjectsKey];
[changedObjects unionSet:objects];
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"SELF IN %@", self.bars];
NSSet *updatedObjects = [changedObjects filteredSetUsingPredicate:predicate];
if (updatedObjects.count > 0) {
NSDate *now = [NSDate date];
if (self.modificationDate == nil || [now timeIntervalSinceDate:self.modificationDate] > 1.0) {
self.modificationDate = now;
}
}
}
@end
答案 0 :(得分:0)
检查何时调用didTurnIntoFault。如果被调用,请尝试:
[[NSNotificationCenter defaultCenter] removeObserver:self]
请注意,contextDidChange通知可能在与didTurnIntoFault不同的线程上调用。所以你可能会遇到竞争条件。确保在同一个线程上完成观察的添加和删除(应该是在其上创建managedOject并因此创建托管对象的线程)。