在iOS 10中正常工作。在将iOS更新为iOS11之后,应用程序崩溃了,同时将数据保存到核心数据,但异常。我已经使用rzvinyl框架进行核心
BOOL isSaved = [currentContext save:&saveErr];
断言失败:(近帕拉梅特 -> mostrecentry == cfarraygetValueAtIndex(堆栈,stackcount -1)),功能 nskeyvalueppendingnotificationperthread,文件 /buildroot/library/caches/com.apple.xbs/sources/foundation_sim/foundation-1444.12/eo.subproj/nskeyvalueobserving.m,第933行。
0 libsystem_kernel.dylib 0x00000001826fd348 __pthread_kill + 8 1 libsystem_pthread.dylib 0x0000000182811354 pthread_kill$VARIANT$mp + 396 2 libsystem_c.dylib 0x000000018266cfd8 abort + 140 3 libsystem_c.dylib 0x0000000182640abc basename_r + 0 4 Foundation 0x00000001834f1a9c -[NSRunLoop+ 178844 (NSRunLoop) runUntilDate:] + 0 5 Foundation 0x00000001834df538 NSKeyValueDidChange + 436 6 Foundation 0x0000000183597ae4 NSKeyValueDidChangeWithPerThreadPendingNotifications + 140 7 CoreData 0x00000001854107c8 -[NSManagedObject didChangeValueForKey:] + 120 8 CoreData 0x0000000185416358 -[NSManagedObject+ 844632 (_NSInternalMethods) _updateFromRefreshSnapshot:includingTransients:] + 692 9 CoreData 0x000000018542e054 -[NSManagedObjectContext+ 942164 (_NestedContextSupport) _copyChildObject:toParentObject:fromChildContext:] + 652 10 CoreData 0x000000018542e4bc -[NSManagedObjectContext+ 943292 (_NestedContextSupport) _parentProcessSaveRequest:inContext:error:] + 804 11 CoreData 0x000000018542f3f0 __82-[NSManagedObjectContext+ 947184 (_NestedContextSupport) executeRequest:withContext:error:]_block_invoke + 580 12 CoreData 0x0000000185431644 internalBlockToNSManagedObjectContextPerform + 92 13 libdispatch.dylib 0x0000000182569048 _dispatch_client_callout + 16 14 libdispatch.dylib 0x0000000182571ae8 _dispatch_queue_barrier_sync_invoke_and_complete + 56 15 CoreData 0x000000018541dd10 _perform + 232 16 CoreData 0x000000018542f0e4 -[NSManagedObjectContext+ 946404 (_NestedContextSupport) executeRequest:withContext:error:] + 172 17 CoreData 0x0000000185387ff8 -[NSManagedObjectContext save:] + 2580
NSManagedObjectContext *currentContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
[[currentContext userInfo] setObject:self forKey:kRZCoreDataStackParentStackKey];
[self performBlock:^{
BOOL hasChanges = [currentContext hasChanges];
if ( !hasChanges) {
RZVLogInfo(@"Managed object context %@ does not have changes, not saving", self);
rzv_performSaveCompletionAsync(completion, nil);
return;
}
NSError *saveErr = nil;
BOOL isSaved = [currentContext save:&saveErr];
if ( !isSaved) {
RZVLogError(@"Error saving managed object context context %@: %@", self, saveErr);
rzv_performSaveCompletionAsync(completion, saveErr);
}
}];
现在有同样的事情,当我遇到您的问题时正在寻找答案。
没有任何答案,我进行了一些深入的调查并找到了原因(至少在我的情况下)。
事实证明,该对象的关系之一是观察KV的更改以更新对象,以更改其值。
触发并更新对象的
,这导致了随着更改的更新,依此类推...
KVO中的此递归引起了崩溃。
确保您要通过willChangeValue
和didChangeValue
观察更改以更新有关此更改的关系,请不要更新观察者,如果观察者是一个设置。
这对您有意义吗?
让我知道是否是这种情况,您需要一个代码样本才能理解这个非常令人困惑的答案。
更新:
我知道我的答案很混乱和含糊,所以我会添加一个例子。
考虑以下内容。我们有两个相互关系的示例类(即反向关系):
class A: NSManagedObject {
@NSManaged var id: NSNumber!
@NSManaged var title: String?
@NSManaged var b: B!
override func willChangeValue(forKey key: String) {
super.willChangeValue(forKey: key)
b?.willChangeValue(forKey: "a")
}
override func didChangeValue(forKey key: String) {
super.didChangeValue(forKey: key)
b?.didChangeValue(forKey: "a")
}
}
class B: NSManagedObject {
@NSManaged var id: NSNumber!
@NSManaged var name: String?
@NSManaged var date: Date?
@NSManaged var a: A!
override func willChangeValue(forKey key: String) {
super.willChangeValue(forKey: key)
a?.willChangeValue(forKey: "b")
}
override func didChangeValue(forKey key: String) {
super.didChangeValue(forKey: key)
a?.didChangeValue(forKey: "b")
}
func setNewA(_ newA: A) {
newA.b = self
a = newA
}
}
我们在每个类中使用willChangeValue
和didChangeValue
来通知其与自身变化的关系。
现在考虑以下代码:
let b = B(context: context)
let a = A(context: context)
b.setNewA(a)
我们使用setNewA
函数来设置反向引用。在该函数中,首先b
将自己分配给a.b
以进行反向引用,然后设置self.a
参考。此时,a
已经知道b
。
稍后会导致willChangeValue
和didChangeValue
在b
上被调用(我们设置a
)。然后a
将拾取更新并通知b
。
从这里开始,尝试猜测它是如何继续的。
这几乎是我发生的事情,有几个小区别。
i覆盖了这些功能,因为我使用的是NSFetchedResultsController
,我需要掌握关系的更改以更新我的UI。
它把我扔到了造成坠机的循环中。
最后,修复程序很简单。A
被修改为:
override func willChangeValue(forKey key: String) {
super.willChangeValue(forKey: key)
guard key != "b" else { return }
b?.willChangeValue(forKey: "a")
}
override func didChangeValue(forKey key: String) {
super.didChangeValue(forKey: key)
guard key != "b" else { return }
b?.didChangeValue(forKey: "a")
}
和 B
以相同的方式修改为:
override func willChangeValue(forKey key: String) {
super.willChangeValue(forKey: key)
guard key != "a" else { return }
a?.willChangeValue(forKey: "b")
}
override func didChangeValue(forKey key: String) {
super.didChangeValue(forKey: key)
guard key != "a" else { return }
a?.didChangeValue(forKey: "b")
}
设置了关系本身(这是多余的),这将防止每个人更新另一个,因为一旦设置了它的属性之一,每个人都已经通知了每个人),从而破坏了周期。
再次,这就是我的终点,这就是修复它的原因。不知道您是否由于同样的原因而遇到问题,但希望它会给您一个想法。
希望现在更容易理解。
如果您仍然难以理解,分享一些代码或直接与我联系,我将尝试并提供帮助。