iOS 11。KVO_IS_RETAINING_ALL_OBSERVERS_OF_THIS_OBJECT_IF_IT_CRASHES_AN_OBSERVER_WAS_OVERRELEASED_OR_SMASHED 是什么意思?

标签 ios crash ios11

在新的 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

谁遇到过这种情况?它是什么以及如何打败它?

最佳答案

它与 KVO = Key-Value Observing 有关。检查您是否正在调用该函数

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))
}

确保将 object 和关键路径替换为您在 addObserver 中使用的相同引用!

更多信息:https://cocoacasts.com/key-value-observing-kvo-and-swift-3/

swift 4/iOS

从 Swift 4/iOS 11 开始,您可以使用 block ,如这个问题: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,例如在 deinitviewWillDisappear 中。

swift 4/macOS

如果您正在为 macOS 10.13 或更高版本开发,在某些情况下不再需要删除它们。引用自文档:

Relaxed Key-Value Observing Unregistration Requirements

Prior to 10.13, KVO would throw an exception if any observers were still registered after an autonotifying object's -dealloc finished running. Additionally, if all observers were removed, but some were removed from another thread during dealloc, the exception would incorrectly still be thrown. This requirement has been relaxed in 10.13, subject to two conditions:

  • The object must be using KVO autonotifying, rather than manually calling -will and -didChangeValueForKey: (i.e. it should not return NO from +automaticallyNotifiesObserversForKey:)
  • The object must not override the (private) accessors for internal KVO state

If all of these are true, any remaining observers after -dealloc returns will be cleaned up by KVO; this is also somewhat more efficient than repeatedly calling -removeObserver methods.

来源:https://developer.apple.com/library/archive/releasenotes/Foundation/RN-Foundation/index.html

关于iOS 11。KVO_IS_RETAINING_ALL_OBSERVERS_OF_THIS_OBJECT_IF_IT_CRASHES_AN_OBSERVER_WAS_OVERRELEASED_OR_SMASHED 是什么意思?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46782372/

相关文章:

ios - 具有适应不同屏幕分辨率的 View 的 MVC 模式

iphone - iPhone崩溃日志:如何找出问题所在

c++ - While循环导致文件崩溃

android - 5.1崩溃-TaskDescription的原色应该是不透明的

ios - 在 iOS 11 中,取消模态呈现的导航 Controller 会导致视觉重复

ios - Realm 中的双嵌套数组(快速)

ios - Restkit映射依赖

ios - 没有名为类 `ChatInboxDelegate` 的类型或协议(protocol)

xcode - 没有自动布局的 iPhone X 界面编程

javascript - 如何解决 iOS 11 Safari getUserMedia "Invalid constraint"问题