In the new iOS11, I get some strange exceptions. I do not understand why this is happening. In the previous iOS, there was no such exception. Log attached:
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
Who ever encountered this? What is it and how to defeat it?
It's related to KVO = Key-Value Observing. Check if you're calling the function
somewhere; that's your KVO observer. This class would also override the function
As the error message says, if you get a crash here, that means the observer was "overreleased" or "smashed". I think that just means it was released while still observing the key path.
How to fix it?
Swift 3
If you need to fix it in Swift 3 (as I did), make sure you call
removeObserver
once you are no longer interested in observing the key path. The easiest way to do that is to add adeinit
method to your observer:Make sure to replace
object
and the key path with the same references you used inaddObserver
!More info: https://cocoacasts.com/key-value-observing-kvo-and-swift-3/
Swift 4 / iOS
From Swift 4 / iOS 11 you can use blocks, as in this question: In Swift 4, how do I remove a block-based KVO observer?
Instead of using the observeValue method, you can just add the observer like so:
In iOS, you should still keep a reference to the observer and call
invalidate
on it at an appropriate time, e.g. indeinit
or inviewWillDisappear
.Swift 4 / macOS
If you're developing for macOS 10.13 or newer, under certain conditions they no longer need to be removed. Quote from the docs:
Source: https://developer.apple.com/library/archive/releasenotes/Foundation/RN-Foundation/index.html