2
1

More than 3 years have passed since last update.

謎のinsertArrangedSubviewでクラッシュする問題

Posted at

筆者が開発しているiOSのアプリで、App Store Connect経由でクラッシュログが繰り返し送られてくるものの、再現方法も解決方法もずっと謎であった不具合が解決したのでメモとして残しておきます。

問題の内容

送られてくるクラッシュログは以下のようなものでした。

Last Exception Backtrace:
0   CoreFoundation                  0x18d2d75b4 __exceptionPreprocess + 220 (NSException.m:199)
1   libobjc.A.dylib                 0x1a12c742c objc_exception_throw + 60 (objc-exception.mm:565)
2   CoreFoundation                  0x18d1d3aac +[NSException raise:format:] + 112 (NSException.m:155)
3   UIKitCore                       0x19001b6d4 -[UIStackView insertArrangedSubview:atIndex:] + 184 (UIStackView.m:103)
4   UIKitCore                       0x18f1723e4 -[_UIButtonBar _layoutBar] + 2576 (UIButtonBar.m:555)
5   UIKitCore                       0x18f175b38 __42-[_UIButtonBarStackView updateConstraints]_block_invoke + 52 (UIButtonBar.m:1293)
6   UIKitCore                       0x190112468 +[UIView(Animation) performWithoutAnimation:] + 104 (UIView.m:13927)
7   UIKitCore                       0x18f175ad8 -[_UIButtonBarStackView updateConstraints] + 120 (UIButtonBar.m:1292)
8   UIKitCore                       0x19003458c -[UIView(AdditionalLayoutSupport) _sendUpdateConstraintsIfNecessaryForSecondPass:] + 484 (NSLayoutConstraint_UIKitAdditions.m:0)
9   UIKitCore                       0x190034a44 -[UIView(AdditionalLayoutSupport) _updateConstraintsIfNeededCollectingViews:forSecondPass:] + 948 (NSLayoutConstraint_UIKitAdditions.m:4409)
10  UIKitCore                       0x190034924 -[UIView(AdditionalLayoutSupport) _updateConstraintsIfNeededCollectingViews:forSecondPass:] + 660 (NSLayoutConstraint_UIKitAdditions.m:4390)
11  UIKitCore                       0x190034924 -[UIView(AdditionalLayoutSupport) _updateConstraintsIfNeededCollectingViews:forSecondPass:] + 660 (NSLayoutConstraint_UIKitAdditions.m:4390)
12  CoreAutoLayout                  0x1a154c060 -[NSISEngine withBehaviors:performModifications:] + 88 (NSISEngine.m:1917)
13  UIKitCore                       0x1900351f4 __100-[UIView(AdditionalLayoutSupport) _updateConstraintsIfNeededWithViewForVariableChangeNotifications:]_block_invoke + 116 (NSLayoutConstraint_UIKitAdditions.m:4455)
14  UIKitCore                       0x190033b30 -[UIView(AdditionalLayoutSupport) _withUnsatisfiableConstraintsLoggingSuspendedIfEngineDelegateExists:] + 128 (NSLayoutConstraint_UIKitAdditions.m:4154)
15  UIKitCore                       0x190034db4 -[UIView(AdditionalLayoutSupport) _updateConstraintsIfNeededWithViewForVariableChangeNotifications:] + 188 (NSLayoutConstraint_UIKitAdditions.m:4454)
16  UIKitCore                       0x190035cac -[UIView(AdditionalLayoutSupport) _updateConstraintsAtEngineLevelIfNeededWithViewForVariableChangeNotifications:] + 436 (NSLayoutConstraint_UIKitAdditions.m:4707)
17  UIKitCore                       0x19010c028 -[UIView _updateConstraintsAsNecessaryAndApplyLayoutFromEngine] + 404 (UIView.m:12304)
18  UIKitCore                       0x18f2659f8 -[UIToolbar layoutSubviews] + 56 (UIToolbar.m:712)
19  UIKitCore                       0x19011f7dc -[UIView(CALayerDelegate) layoutSublayersOfLayer:] + 2500 (UIView.m:17460)
20  QuartzCore                      0x190627464 -[CALayer layoutSublayers] + 296 (CALayer.mm:10129)
21  QuartzCore                      0x190627920 CA::Layer::layout_if_needed(CA::Transaction*) + 524 (CALayer.mm:9996)
22  QuartzCore                      0x19063bd48 CA::Layer::layout_and_display_if_needed(CA::Transaction*) + 144 (CALayer.mm:2478)
23  QuartzCore                      0x1905833e4 CA::Context::commit_transaction(CA::Transaction*, double, double*) + 416 (CAContextInternal.mm:2380)
24  QuartzCore                      0x1905ae6dc CA::Transaction::commit() + 732 (CATransactionInternal.mm:449)
25  QuartzCore                      0x1905afa3c CA::Transaction::observer_callback(__CFRunLoopObserver*, unsigned long, void*) + 96 (CATransactionInternal.mm:925)
26  CoreFoundation                  0x18d253454 __CFRUNLOOP_IS_CALLING_OUT_TO_AN_OBSERVER_CALLBACK_FUNCTION__ + 36 (CFRunLoop.c:1799)
27  CoreFoundation                  0x18d24d868 __CFRunLoopDoObservers + 576 (CFRunLoop.c:1912)
28  CoreFoundation                  0x18d24de18 __CFRunLoopRun + 1056 (CFRunLoop.c:2953)
29  CoreFoundation                  0x18d24d4cc CFRunLoopRunSpecific + 600 (CFRunLoop.c:3242)
30  GraphicsServices                0x1a3c31820 GSEventRunModal + 164 (GSEvent.c:2259)
31  UIKitCore                       0x18fbf2a28 -[UIApplication _run] + 1072 (UIApplication.m:3270)
32  UIKitCore                       0x18fbf8104 UIApplicationMain + 168 (UIApplication.m:4739)
33  KifuBox                         0x102e6c2b0 main + 68 (WaitingViewController.swift:12)
34  libdyld.dylib                   0x18cf14e60 start + 4

厄介な点の1つとして、自分が直接書いたソースコードはスタック中にはなく、何をトリガに起きているのかわからないことがありました。
最終的にはUIStackViewinsertArrangedSubviewで落ちており、スタックの途中には_UIButtonBarStackViewなどが出ているので、多分UIBarButtonItemに関連する何かだとは思うのですが、どこで問題が起きているのか全くわかりませんでした。

発生の傾向を見ると、iOS13.4以降でしか起きていないようで、それがiOS13.4以降でしか発生しない現象なのか、たまたま時期的な関係でそう見えているのかはよくわかりませんでした。

原因と解決方法

結論としては、Apple Developers Forumにあった以下の記事が当たりでした。
https://developer.apple.com/forums/thread/130038

上記記事ではUIAlertControllerだそうですが、筆者のアプリでは画面下部のUIToolbarUIBarButtonItemを追加する際に、同じオブジェクトが含まれていると、iOS13.4以降ではクラッシュするという問題でした。(iOS13.3以前では同じコードでも問題は発生しない)

MyViewController.swift
self.setToolbarItems([filterButton, fixSpace1, dummyIcon, flexSpace1, filterStateButton,
     flexSpace2, dummyIcon, fixSpace2, dummyIcon], animated: true)

上記のソースコードが問題で、ツールバーにボタンを並べる際のレイアウト調整のために、見えないダミーのボタン(dummyIcon)を3つ追加していたのですが、その3つが同じオブジェクトであったためにクラッシュしていました。

以下のように3つ別のオブジェクトにすることで解決しました(オブジェクトの生成コード等は省略)

MyViewController.swift
self.setToolbarItems([filterButton, fixSpace1, dummyIcon1, flexSpace1, filterStateButton,
     flexSpace2, dummyIcon2, fixSpace2, dummyIcon3], animated: true)

手がかりがinsertArrangedSubviewくらいしかなくて難航したので、少しでもネット上で情報が見つかるように記事を書いてみました。

2
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
1