Hello, I am looking for some help today about a crash that randomly appeared for no explicit reason. A bit of context, I have 2 apps/targets within the project and the only thing that changes between the two is pretty much the API and the colors/logos.
I have published an update for both apps, the related code hasn't changed since the previous versions (it has been in production for 6 months already), and it's only crashing in the same app, not in the other one somehow. It happens on multiple iOS versions and devices as well. Of course, I am unable to reproduce the crash.
I am using Firebase Crashlytics, which gives me this error message :
Fatal Exception: NSInternalInconsistencyException - You must provide a value (key=contents)
And in the Xcode Organizer, the highlighted stack trace line responsible for the crash is the following :
3 UIKitCore 0x1c2ad5970 -[_UIViewDeferredAnimation addAnimationFrameForValue:] + 216 (UIView.m:2792)
About the code, I have a custom searchBar and a cancelButton embedded in a UIStackView, I am animating the cancelButton visibility using .isHidden to replicate the experience you get when using a UISearchController in the navigationBar.
About the crash, it seems to be triggered when animating keyframes using UIView.animateKeyframes, with multiple UIView.addKeyframe within the animation block, at least that's why I understand from the stack trace.
The code is really simple, when the searchBarTextField becomes the first responder and begins editing, I animate the cancelButton in. The cancelButtonAnimationOptions are the followings : .curveEaseInOut, .beginFromCurrentState and .allowUserInteraction.
func textFieldDidBeginEditing(_ textField: UITextField) {
showSearchBarCancelButton()
}
func showSearchBarCancelButton() {
let duration = Layout.animationDuration
let options = Layout.cancelButtonAnimationOptions
UIView.animateKeyframes(withDuration: duration, delay: 0, options: options, animations: {
UIView.addKeyframe(withRelativeStartTime: 0.0, relativeDuration: 1, animations: {
self.cancelButton.isHidden = false
self.cancelButton.superview?.layoutIfNeeded()
})
UIView.addKeyframe(withRelativeStartTime: 0.7, relativeDuration: 0.3, animations: {
self.cancelButton.alpha = 1
})
})
}
Here is a preview of the stack trace :
(Check Log.crash in the attachments for the full version) :
Exception Type: EXC_CRASH (SIGABRT)
Exception Codes: 0x0000000000000000, 0x0000000000000000
Triggered by Thread: 0
Last Exception Backtrace:
0 CoreFoundation 0x1c057de88 __exceptionPreprocess + 164 (NSException.m:202)
1 libobjc.A.dylib 0x1b98ab8d8 objc_exception_throw + 60 (objc-exception.mm:356)
2 Foundation 0x1bae99b4c -[NSAssertionHandler handleFailureInMethod:object:file:lineNumber:description:] + 188 (NSException.m:242)
3 UIKitCore 0x1c2ad5970 -[_UIViewDeferredAnimation addAnimationFrameForValue:] + 216 (UIView.m:2792)
4 UIKitCore 0x1c2ad5208 -[_UIViewDeferredKeyframeAnimation addAnimationFrameForValue:] + 72 (UIView.m:2901)
5 UIKitCore 0x1c2ad5148 __93-[UIViewKeyframeAnimationState addKeyframeWithRelativeStartTime:relativeDuration:animations:]_block_invoke + 368 (UIView.m:2651)
6 CoreFoundation 0x1c0587588 __NSDICTIONARY_IS_CALLING_OUT_TO_A_BLOCK__ + 24 (NSDictionaryHelpers.m:10)
7 CoreFoundation 0x1c0611bc0 -[__NSDictionaryM enumerateKeysAndObjectsWithOptions:usingBlock:] + 212 (NSDictionaryM_Common.h:311)
8 UIKitCore 0x1c2b636c8 -[UIViewKeyframeAnimationState addKeyframeWithRelativeStartTime:relativeDuration:animations:] + 156 (UIView.m:2638)
9 UIKitCore 0x1c2b635dc +[UIView(UIViewKeyframeAnimations) addKeyframeWithRelativeStartTime:relativeDuration:animations:] + 132 (UIView.m:15468)
10 MyApp 0x102b657f8 closure #1 in FavoritesViewController.showSearchBarCancelButton() + 196 (FavoritesViewController+Search.swift:45)
11 MyApp 0x102c04198 thunk for @escaping @callee_guaranteed () -> () + 28 (<compiler-generated>:0)
12 UIKitCore 0x1c28011e4 +[UIView _setupAnimationWithDuration:delay:view:options:factory:animations:start:animationStateGenerator:completion:] + 512 (UIView.m:15213)
13 UIKitCore 0x1c292e140 +[UIView(UIViewKeyframeAnimations) animateKeyframesWithDuration:delay:options:animations:completion:] + 156 (UIView.m:15458)
14 MyApp 0x102b655a4 FavoritesViewController.showSearchBarCancelButton() + 44 (FavoritesViewController+Search.swift:44)
15 MyApp 0x102b655a4 FavoritesViewController.textFieldDidBeginEditing(_:) + 44 (FavoritesViewController+Search.swift:12)
16 MyApp 0x102b655a4 @objc FavoritesViewController.textFieldDidBeginEditing(_:) + 224 (<compiler-generated>:11)
17 UIKitCore 0x1c2c949c8 -[UITextField _notifyDidBeginEditing] + 104 (UITextField.m:1910)
18 UIKitCore 0x1c2952554 -[UITextField _becomeFirstResponder] + 196 (UITextField.m:1842)
19 UIKitCore 0x1c294ffa4 -[UIResponder becomeFirstResponder] + 516 (UIResponder.m:392)
20 UIKitCore 0x1c294fd90 -[UIView(Hierarchy) becomeFirstResponder] + 120 (UIView.m:12379)
21 UIKitCore 0x1c2803bc4 -[UITextField becomeFirstResponder] + 152 (UITextField.m:1496)
22 MyApp 0x102ab6840 CustomSearchBar.onSearchBarTap(_:) + 36 (CustomSearchBar.swift:36)
23 MyApp 0x102ab6840 @objc CustomSearchBar.onSearchBarTap(_:) + 88 (<compiler-generated>:35)
Thanks for your help!