Releaseビルドでのみクラッシュするアプリへ行った対策について
こんにちは!
モバイルアプリサービス部の田中孝明です。
今回はXcode 8.1 + Swift 2.3の環境でReleaseビルドをかけるとアプリがDebug時には起きなかった場所でクラッシュするようになった問題にあたった時、急遽対策を行った内容を共有したいと思います。
経緯
Xcode 7.3 + Swift 2.1で作成されていたあるプロジェクトをiOS 10に対応するためにXcode 8.1とSwift 2.3に対応させていました。
Swift 3.0ではなく、Swift 2.3なのは3.0対応のライブラリがiOS 9以上が対象だったため、Deployment Target がiOS 8のプロジェクトは移行できなかった側面があります。
今回Releaseビルドを行って実機で確認したところ、Alamofireのエラーハンドリング処理でクラッシュするようになってしまいました。
Thread 0 name: Dispatch queue: com.apple.main-thread Thread 0 Crashed: 0 libobjc.A.dylib 0x0000000197b37bdc objc_msgSend + 28 1 libswiftCore.dylib 0x00000001013f48a8 0x101340000 + 739496 2 libswiftCore.dylib 0x00000001013f475c 0x101340000 + 739164 3 libswiftCore.dylib 0x00000001013f73f0 0x101340000 + 750576 4 Foundation 0x0000000188200040 -[NSError dealloc] + 68 5 MyApp 0x00000001001441bc Foo.(hoge(completion : (NSError?) -> ()) -> ()).(closure #1) (Foo.swift:61) 6 MyApp 0x00000001001b385c Bar.(request(completionHandler : (json : AnyObject?, date : NSDate?, error : NSError?) -> ()) -> Request).(closure #1) (Bar.swift:241) 7 MyApp 0x00000001001bab70 partial apply for Bar.(request(completionHandler : (json : AnyObject?, date : NSDate?, error : NSError?) -> ()) -> Request).(closure #1) (Bar.swift:0) 8 Alamofire 0x0000000100820960 partial apply for thunk (ResponseSerialization.swift:0) 9 Alamofire 0x0000000100820498 specialized Request.(response<A where ...> (queue : OS_dispatch_queue?, responseSerializer : A, completionHandler : (Response<A.SerializedObject, A.ErrorObject>) -> ()) -> Self).(closure #1).(closure #1) (ResponseSerialization.swift:142) 10 libdispatch.dylib 0x00000001981693a8 _dispatch_call_block_and_release + 20 11 libdispatch.dylib 0x0000000198169368 _dispatch_client_callout + 12 12 libdispatch.dylib 0x000000019816d97c _dispatch_main_queue_callback_4CF + 928 13 CoreFoundation 0x00000001873d1fa0 __CFRUNLOOP_IS_SERVICING_THE_MAIN_DISPATCH_QUEUE__ + 8 14 CoreFoundation 0x00000001873d0048 __CFRunLoopRun + 1488 15 CoreFoundation 0x00000001872fd0a0 CFRunLoopRunSpecific + 392 16 GraphicsServices 0x00000001904a75a0 GSEventRunModal + 164 17 UIKit 0x000000018bc323bc UIApplicationMain + 1484 18 MyApp 0x00000001000ad570 main (AppDelegate.swift:14) 19 libdyld.dylib 0x0000000198192a04 start + 0
NSError
のdealoc
をコールした後にクラッシュしています。
対策
詳しい原因については追って調査中ですが、対策としてReleaseビルド時の最適化を他のビルド設定と同じにしました。
Xcodeのプロジェクトのターゲットを選択し、Build Settings
を選択します。
Optimization
の項目を選択し、最適化の設定を確認します。
Release
の設定をNone
に変更します。
本対策は最適な解決手段では無いことをご了承ください。
最適化をやめることでバイナリのサイズや処理時間の改善に影響を及ぼす可能性はあります。
まとめ
一応バグレポートとして報告しましたので、後のXcodeのバージョンによっては直る可能性もあります。
また、Swift 2.3ではなく、Swift 3.0に移行した際には掲題のような問題は起きない可能性もあります。
Xcode 8.1 + Swift 2.3という限定的な環境でのアクシデントでしたが、同じようなトラブルで悩まれている方の助けになれば幸いです。