Karakuri.com

ベンチャー企業で働くソフトウェアエンジニアの技術録

Swiftで一部の画面の回転禁止を導入したらiOS9はsupportedInterfaceOrientations was invoked recursivelyと例外が飛んでクラッシュする

スポンサーリンク

iOSアプリ開発で、デザインの問題で一部の画面だけ回転を禁止にする必要が生じました。この一部の画面だけ回転を禁止するというのはUX的に問題があるのはそうなのですが、同時にAppleとしても推奨していないことのような気がします。案の定、iOS9でクラッシュするという不具合を作ってしまったので、今回はその原因と対策についてまとめます。

一部の画面だけ回転禁止にする方法

shouldAutorotateとsupportedInterfaceOrientationsをoverrideする

画面回転時に呼ばれるshouldAutorotateとsupportedInterfaceOrientationsをオーバーライドして回転をキャンセルすることができます。
qiita.com
qiita.com

iOS9でUIAlertControllerがクラッシュする

supportedInterfaceOrientations was invoked recursivelyと例外が飛ぶ

するとお客さんからダイアログ表示するときにアプリがクラッシュすると連絡が来ました。Firebase Cashlyticsを確認してみると、supportedInterfaceOrientations was invoked recursivelyという例外が。直感的に画面回転関係だとは例外からは推測できますが、UIAlertControllerの表示時に起きるというのは謎です。しかもiOS9でだけ。

iOS9に無限ループに陥るバグがあるらしい

調べてみるとiOS9ではshouldAutorotateとsupportedInterfaceOrientationsをオーバーライドすると無限ループに陥るバグがあるそうです…。
stackoverflow.com

問題の解決方法

UIAlertControllerを拡張して解決

先のstackoverflowにも書いてありますが、対策としてはUIAlertControllerを拡張して無限ループに陥らないようにすれば良いようです。

import Foundation
import UIKit

extension UIAlertController {
    open override var shouldAutorotate: Bool {
        return true
    }
    
    open override var supportedInterfaceOrientations: UIInterfaceOrientationMask {
        return .all
    }
}