Xcode 11.2 + Storyboard UITextView でクラッシュ
Xcode 11.2 で Storyboard か xib で UITextView
を使っていると iOS 13.2 より前のバージョンでクラッシュするという凶悪なバグが発生している。
実際にクラッシュを起こしてみると以下の様に _UITextLayoutView
ってクラスは無いとエラーメッセージが表示された。
*** Terminating app due to uncaught exception 'NSInvalidUnarchiveOperationException', reason: 'Could not instantiate class named _UITextLayoutView because no class named _UITextLayoutView was found; the class needs to be defined in source code or linked in from a library (ensure the class is part of the correct target)'
Stack Overflow
Apple Developer Forums
これらの書き込みをまとめると
- 影響範囲は現行最新版の iOS 13.2 より前の全てのバージョン
- 発生条件は Storyboard か xib で
UITextView
を使っている事 - 回避策1
UITextView
を全てコードで生成する - 回避策2 Xcode 11.1 を使う
回避策については Apple の人も同様に言っている https://forums.developer.apple.com/thread/125287#391939
対策
UITextView
の Storyboard 生成をコード生成に置き換えるかどうかはプロジェクト次第(コスト次第)だと思う。
もしソースの公開されていない外部ライブラリを使っている場合、中でどういう実装をしているのか分からないので Xcode 11.1 に戻した方が無難そう。
何らかの事情で Xcode 11.2 を使い続ける場合、配布ビルドのみ Xcode 11.1 で行うのもアリかと。
余談
Developer Forums に _UITextLayoutView
を動的に追加すれば良いなんてコメントもあった。
https://forums.developer.apple.com/thread/125287#391979
なるほどと思い実際に試してみたところ以下の Objective-C 実装を application(_:didFinishLaunchingWithOptions:)
のタイミングで実行する事で iOS 12 でもクラッシュを回避する事ができた。
がしかしコメントにもある様に、実際にこの実装でリリースするのは如何なものかいう感じなので次のバージョンの Xcode が出るまでの開発中の一時凌ぎとして使うならといったところ。興味が湧いて実装しただけなので参考までに。*1
@interface UITextViewWorkaround : NSObject + (void)executeWorkaround; @end @implementation UITextViewWorkaround + (void)executeWorkaround { if (@available(iOS 13.2, *)) { } else { const char *className = "_UITextLayoutView"; Class cls = objc_getClass(className); if (cls == nil) { cls = objc_allocateClassPair([UIView class], className, 0); objc_registerClassPair(cls); #if DEBUG printf("added %s dynamically\n", className); #endif } } } @end
_UITextLayoutView
の superClass
が UIView
である事は以下の記事の方法で確認した。
以上
追記
iOS と tvOS については Xcode 11.2.1 GM で修正された。
https://developer.apple.com/documentation/xcode_release_notes/xcode_11_2_1_gm_seed_release_notes/
*1:この実装を掲載した後まるっと StackOverflow に転載されていてびっくり