酢ろぐ!

カレーが嫌いなスマートフォンアプリプログラマのブログ。

Xcode 13.1でAdHocバイナリのエクスポート中にXcodeがクラッシュする問題 〜無限ビルド編〜

M1チップ(Apple Silicon)搭載のMacBook Pro (16-inch, 2021)に移行した。社内の開発環境の足並みを合わせるため、すべてのアプリで Rosettaを使わずに実機およびiOSシミュレータでデバッグ実行できるようにしたかった。

使用しているライブラリやソースコードの量の少ない個人開発アプリでは手間が掛かったものの、比較的簡単にM1 Macの実機・iOSシミュレータでデバッグ実行ができるようになった。

お仕事で開発しているアプリは、ほとんどが年代物な上にたくさんのライブラリを導入している関係で、M1で動かすのに試行錯誤するハメになった。.xcframeworkを使いたいので、Carthageに対応しているライブラリはすべてCarthageでインストールするように切り替えていった。

実機でのデバッグ実行とアーカイブの対応が終わったが、どうしてもiOSシミュレータでの実行ができなくて頭を捻っていた。翌日同僚に助けてもらってiOSシミュレータで実行できるように設定を見直してもらった🌻🌷

これでM1 Macへの移行が完了したと思っていたのだが、AdHocバイナリをエクスポート中にXcodeがクラッシュする問題が発生してしまい、文化の日は一日ビルドして過ごすことになった。

AdHocバイナリのエクスポート中にXcode.appがクラッシュする問題が発生した

現象としては以下の通りである。

  • 実機デバッグできる
  • iOSシミュレータで実行できる
  • アプリのアーカイブに成功する
  • AppStoreバイナリのエクスポートができる
  • AdHocバイナリのエクスポート中にXcode.appがクラッシュする ← なぜ?

クラッシュ時のログが表示されるが何が悪いのかまったくわからない。

Crashed Thread:        9  Dispatch queue: ConcurrentQueue: -[IDEDistributionPackagingStepViewController viewDidInstall]_block_invoke

Exception Type:        EXC_CRASH (SIGABRT)
Exception Codes:       0x0000000000000000, 0x0000000000000000
Exception Note:        EXC_CORPSE_NOTIFY

Application Specific Information:
UNCAUGHT EXCEPTION (NSInvalidArgumentException): -[NSNull path]: unrecognized selector sent to instance 0x21ff58340
UserInfo: (null)
Open FDs: 61/9472
Hints:
0: Calling block provided by:
0   DVTDispatchAsync (in DVTFoundation)
1   DVTAsyncPerformBlock (in DVTFoundation)
2   -[IDEDistributionPackagingStepViewController viewDidInstall] (in IDEKit)
3   -[DVTViewController _viewDidInstall] (in DVTViewControllerKit)
4   -[_DVTViewController_ViewLifecycleInterpositions viewDidMoveToWindow] (in DVTViewControllerKit)
5   -[NSView _setWindow:] (in AppKit)
6   -[NSView addSubview:] (in AppKit)
7   -[NSView setSubviews:] (in AppKit)
8   -[DVTBorderedView setContentView:] (in DVTUserInterfaceKit)
9   -[IDEDistributionAssistantWindowController setDistributionStepViewController:] (in IDEKit)
10   -[NSObject(NSKeyValueObservingPrivate) _changeValueForKeys:count:maybeOldValuesDict:maybeNewValuesDict:usingBlock:] (in Foundation)
11   -[NSObject(NSKeyValueObservingPrivate) _changeValueForKey:key:key:usingBlock:] (in Foundation)
12   _NSSetObjectValueAndNotify (in Foundation)
13   -[IDEDistributionAssistantWindowController next:] (in IDEKit)
14   __79-[IDEDistributionAutomaticSigningAssetsStepViewController _locateSigningAssets]_block_invoke_2 (in IDEKit)
15   __DVT_CALLING_CLIENT_BLOCK__ (in DVTFoundation)
16   ___DVTAsyncPerformBlockOnMainRunLoop_block_invoke (in DVTFoundation)
17   __CFRUNLOOP_IS_CALLING_OUT_TO_A_BLOCK__ (in CoreFoundation)
18   __CFRunLoopDoBlocks (in CoreFoundation)
19   __CFRunLoopRun (in CoreFoundation)
20   CFRunLoopRunSpecific (in CoreFoundation)
21   RunCurrentEventLoopInMode (in HIToolbox)
22   ReceiveNextEventCommon (in HIToolbox)
23   _BlockUntilNextEventMatchingListInModeWithFilter (in HIToolbox)
24   _DPSNextEvent (in AppKit)
25   -[NSApplication(NSEvent) _nextEventMatchingEventMask:untilDate:inMode:dequeue:] (in AppKit)
26   -[DVTApplication nextEventMatchingMask:untilDate:inMode:dequeue:] (in DVTKit)
27   -[NSApplication run] (in AppKit)
28   -[DVTApplication run] (in DVTKit)
29   NSApplicationMain (in AppKit)
30   start (in dyld)

Stack Overflowで調べてみると、AdHocバイナリをexoprt中にXcodeがクラッシュする不具合は昔からよくあるみたい。ただ「これ」をしたら治るって解決策がなにひとつ掲示されていない。

思い当たることをひとつずつ対応してビルド&エクスポートできるかを確認していくことになった。無限ビルド編である。

解決編(?)

色々試したが本不具合に対しては関係がなかったようで、AdHocエクスポート中にXcodeがクラッシュした。

  • Carthageのキャッシュをすべて削除して、.xcframeworkを作成しなおす
  • pod deintegrate してからの pod install を実行する
  • DerivedDataを削除して、macOSの再起動する
  • Provisioning Profileをすべて削除、現在使っている証明書をrevokeして、新しく証明書を作成、Provisioning Profileも作り直す

最終的に.xcframeworks の依存関係を修正することで問題が解決した。

当該アプリではプッシュ通知の管理にOneSignalを使っている。OneSignalは、アプリにNotification Service Extensionを追加して利用することになっている。

documentation.onesignal.com

アプリでは実行時にOneSignal SDKに対してユーザーIDを設定する必要がある。よって依存関係として下記のように設定していた。

  • app
    • (Embedded Frameworkとして) OneSignal.xcframework
  • notification_service_extension
    • (Embedded Frameworkとして) OneSignal.xcframework

しかし実際にはextensionはappにEmbedded Frameworkとして含まれるので、下記のような依存関係になっていた。

  • app
    • (Embedded Frameworkとして) OneSignal.xcframework
    • (Embedded Frameworkとして) notification_service_extension
      • (Embedded Frameworkとして) OneSignal.xcframework

このためAdHocエクスポート時にXcodeがクラッシュする謎の現象が発生していた。AppStoreエクスポートや実機でのデバッグ時になぜクラッシュしないのかは不思議である。下記のように依存関係を修正することでエクスポート時にXcodeがクラッシュする現象を回避することができた。

  • app
    • (Embedded Frameworkとして) OneSignal.xcframework (Embed & Sign)
    • (Embedded Frameworkとして) notification_service_extension
      • (Embedded Frameworkとして) OneSignal.xcframework (Do Not Embed)

無限ビルド編、終わり。

2021/11/09追記

anzさんも同様の問題に引っかかっていたみたいで、類似ケースとしてリンクを置いておきます。

blog.anzfactory.xyz