在新的iOS11中,我得到了一些奇怪的异常。我不明白为什么会发生这样的事情。在以前的iOS中,没有这样的例外。附加的日志:
Crashed: com.apple.main-thread
0 libobjc.A.dylib 0x180a5e7e8 object_isClass + 16
1 Foundation 0x181f013e8 KVO_IS_RETAINING_ALL_OBSERVERS_OF_THIS_OBJECT_IF_IT_CRASHES_AN_OBSERVER_WAS_OVERRELEASED_OR_SMASHED + 68
2 Foundation 0x181eff8ec NSKeyValueWillChangeWithPerThreadPendingNotifications + 300
3 QuartzCore 0x18555a6dc CAAnimation_setter(CAAnimation*, unsigned int, _CAValueType, void const*) + 156
4 QuartzCore 0x18555d388 -[CAPropertyAnimation setKeyPath:] + 32
5 UIKit 0x18a9b1a08 -[UIImageView startAnimating] + 876
6 UIKit 0x18a9b0e78 -[UIActivityIndicatorView startAnimating] + 48
7 UIKit 0x18a9b0174 -[UIActivityIndicatorView _didMoveFromWindow:toWindow:] + 212
8 UIKit 0x18a95845c -[UIView(Internal) _didMoveFromWindow:toWindow:] + 712
9 UIKit 0x18a95845c -[UIView(Internal) _didMoveFromWindow:toWindow:] + 712
10 UIKit 0x18a95845c -[UIView(Internal) _didMoveFromWindow:toWindow:] + 712
11 UIKit 0x18a95845c -[UIView(Internal) _didMoveFromWindow:toWindow:] + 712
12 UIKit 0x18a95845c -[UIView(Internal) _didMoveFromWindow:toWindow:] + 712
13 UIKit 0x18a95845c -[UIView(Internal) _didMoveFromWindow:toWindow:] + 712
14 UIKit 0x18a95845c -[UIView(Internal) _didMoveFromWindow:toWindow:] + 712
15 UIKit 0x18a95845c -[UIView(Internal) _didMoveFromWindow:toWindow:] + 712
16 UIKit 0x18a957918 __45-[UIView(Hierarchy) _postMovedFromSuperview:]_block_invoke + 156
17 Foundation 0x181e7c59c -[NSISEngine withBehaviors:performModifications:] + 168
18 UIKit 0x18a95778c -[UIView(Hierarchy) _postMovedFromSuperview:] + 824
19 UIKit 0x18a96339c -[UIView(Internal) _addSubview:positioned:relativeTo:] + 1728
20 UIKit 0x18abb3158 __53-[_UINavigationParallaxTransition animateTransition:]_block_invoke_2 + 1660
21 UIKit 0x18a969a84 +[UIView(Animation) performWithoutAnimation:] + 104
22 UIKit 0x18ab23864 __53-[_UINavigationParallaxTransition animateTransition:]_block_invoke + 264
23 UIKit 0x18ac418a4 +[UIView(Internal) _performBlockDelayingTriggeringResponderEvents:] + 220
24 UIKit 0x18ab2321c -[_UINavigationParallaxTransition animateTransition:] + 1112
25 UIKit 0x18aae1720 -[UINavigationController _startCustomTransition:] + 3444
26 UIKit 0x18aa02e04 -[UINavigationController _startDeferredTransitionIfNeeded:] + 712
27 UIKit 0x18aa02a34 -[UINavigationController __viewWillLayoutSubviews] + 124
28 UIKit 0x18aa0295c -[UILayoutContainerView layoutSubviews] + 188
29 UIKit 0x18a959000 -[UIView(CALayerDelegate) layoutSublayersOfLayer:] + 1256
30 QuartzCore 0x1855290b4 -[CALayer layoutSublayers] + 184
31 QuartzCore 0x18552d194 CA::Layer::layout_if_needed(CA::Transaction*) + 332
32 QuartzCore 0x18549bf24 CA::Context::commit_transaction(CA::Transaction*) + 336
33 QuartzCore 0x1854c2340 CA::Transaction::commit() + 540
34 QuartzCore 0x1854c3180 CA::Transaction::observer_callback(__CFRunLoopObserver*, unsigned long, void*) + 92
35 CoreFoundation 0x1814f38b8 __CFRUNLOOP_IS_CALLING_OUT_TO_AN_OBSERVER_CALLBACK_FUNCTION__ + 32
36 CoreFoundation 0x1814f1270 __CFRunLoopDoObservers + 412
37 CoreFoundation 0x1814f182c __CFRunLoopRun + 1292
38 CoreFoundation 0x1814122d8 CFRunLoopRunSpecific + 436
39 GraphicsServices 0x1832a3f84 GSEventRunModal + 100
40 UIKit 0x18a9bf880 UIApplicationMain + 208
有谁遇到过这种情况?它是什么?如何战胜它?
发布于 2017-10-25 21:08:22
它与KVO =键值观察有关。检查您是否在调用函数
object.addObserver(self, forKeyPath:..., options:..., context:...)某处;那是你的KVO观察者。这个类还会重写函数
observeValue(forKeyPath:of:change:context:)正如错误消息所说,如果你在这里得到一个崩溃,这意味着观察者是“过度释放”或“粉碎”。我认为这只是意味着它是在观察关键路径的同时发布的。
如何修复它?
Swift 3
如果您需要在Swift 3中修复它(就像我做的那样),请确保在您对观察密钥路径不再感兴趣时调用removeObserver。最简单的方法是向观察者添加一个deinit方法:
deinit {
object.removeObserver(self, forKeyPath:#keyPath(same.as.in.addObserver))
}确保用在addObserver中使用的相同引用替换object和键路径!
更多信息:https://cocoacasts.com/key-value-observing-kvo-and-swift-3/
Swift 4/ iOS
在Swift 4/ iOS 11中,您可以使用块,如下面的问题所示:In Swift 4, how do I remove a block-based KVO observer?
您可以像这样添加观察者,而不是使用observeValue方法:
var observer: NSKeyValueObservation? = foo.observe(.value, options: [.new]) { (foo, change) in
print(change.newValue) // whatever needs to happen when the value changes
}在iOS中,您仍然应该保留对观察者的引用,并在适当的时间对其调用invalidate,例如在deinit或viewWillDisappear中。
Swift 4/ macOS
如果您正在为macOS 10.13或更高版本进行开发,在某些情况下不再需要删除它们。引用自文档:
放宽了Key-Value观察注销要求
在10.13之前,如果任何观察者在自动通知对象的-dealloc完成运行后仍被注册,KVO将抛出异常。此外,如果所有观察者都被移除,但在dealloc过程中从另一个线程中移除了一些观察者,则仍然会错误地抛出异常。这一要求在10.13中有所放宽,但必须满足两个条件:
对象必须使用KVO自动通知,而不是手动调用-will和-didChangeValueForKey:(即,它不应从+automaticallyNotifiesObserversForKey:)
的()访问器
如果所有这些都是真的,那么-dealloc返回后剩下的任何观察者都将被KVO清理掉;这也比重复调用-removeObserver方法更有效率。
来源:
https://stackoverflow.com/questions/46782372
复制相似问题