iPhone, Android等のスマートフォン向けアプリ開発などの話題を中心に、時事ネタなどを気の向くままに書いています。
Home
 

iOS8の自爆機能について(笑)




先日まとめた「iOS8向けアプリ開発時の注意点」には多くの方が見に来られた様で何よりです。
iOS8向けアプリ開発時の注意点」にも記載しましたが、iOS8を搭載したiPadでは呼び出すだけでアプリをクラッシュさせてくれる機能があります。

ウチでは、この「呼び出すだけでアプリをクラッシュさせてくれる機能」の事を親しみを込めて「自爆機能」と呼んでいます(笑)

この「自爆機能」はビルド時にエラー、警告は一切出ません。
加えて、APIドキュメントには特に記載はありません。
そして、アプリ実行中にその機能を使うと容赦なくアプリをクラッシュさせます(笑)

この「自爆機能」に付いては余り情報が無いので、かなり困る方も多いと思います。
そこで、備忘録を兼ねて「自爆機能」に関してまとめたいと思います。
間違い等がありましたならばご指摘ください。

なお、以下の情報はiPadのみの話であり、iPhoneには今の所関係はありません。

 

「自爆機能」の発動条件

まず、iPadではActionSheetが使えません。
厳密に言えば、ActionSheetを使わずにPopoverで表示するのが基本となっています。
この部分はiOS8に限らず、以前からそうでしたね。

ActionSheetに関しては、独自に開発した機能であれば使っているかどうかは当然わかります。
しかし、UIKit内で提供する機能がActionSheetを使用している場合は知らずに使用してしまう事があるかと思います。
そして、この部分が「自爆機能」を発動する条件になります。

 

「自爆機能」の発動条件の詳細

iOS8では透過UIViewControllerを作成する事が可能になりました。
DeprecatedになったUIAlertView、UIActionSheetの代わりに使用するUIAlertControllerはまさにこの透過UIViewControllerを使用しているものと思われます。
※透過UIViewControllerの説明は省略します(笑)

つまり、UIKitの提供するUIViewControllerが内部的にActionSheetとPopoverを切り分けて使用しているかどうかを知らないと実行時に自爆機能が発動する事になります。
※内部的にはUIPopoverPresentationControllerクラスを使用してPopoverを管理している様です。

上にも書きましたが、ビルドエラーはありませんし、APIドキュメントには特に記載が無いため、この自爆機能を埋め込んでしまう可能性もあるため、注意が必要になります。

 

「自爆機能」が発動するUIViewController

iPadで上記の「自爆機能」発動条件に当てはまるUIViewControllerは3つありました。
まだ存在する可能性はありますが、今の所ウチが認識しているのは以下の3つです。
※各UIViewControllerの説明は省きます(笑)

  • UIActivityViewController
  • UIAlertController
  • UIDocumentMenuViewController

ちなみに、これらのUIViewControllerの共通点は、UIViewControllerの以下のメソッドで表示しています。
※厳密にはこのメソッドを使うかどうかはほとんど関係ないと思います。
※また、他の方法でも表示できるのかも知れませんが、ドキュメント通りだとそうなるかと思います。

- (void)presentViewController:(UIViewController *)viewControllerToPresent
                    animated: (BOOL)flag
                  completion:(void (^)(void))completion

そして、iPadでの実行時に呼び出すと以下の様なエラーを出力してアプリがクラッシュします。
※この出力はUIAlertControllerのものです。

2014-09-09 01:48:51.849 Wrix[3332:84506] *** Terminating app due to uncaught exception 'NSGenericException', reason: 'UIPopoverPresentationController (<_UIAlertControllerActionSheetRegularPresentationController: 0x7ff59d1c84a0>) should have a non-nil sourceView or barButtonItem set before the presentation occurs.'
 *** First throw call stack:
 (
 0 CoreFoundation 0x000000010c0533e5 __exceptionPreprocess + 165
 1 libobjc.A.dylib 0x000000010bc40967 objc_exception_throw + 45
 2 CoreFoundation 0x000000010c05331d +[NSException raise:format:] + 205
 3 UIKit 0x000000010ac2773b -[UIPopoverPresentationController presentationTransitionWillBegin] + 334
 4 UIKit 0x000000010a61a977 __71-[UIPresentationController _initViewHierarchyForPresentationSuperview:]_block_invoke + 1398
 5 UIKit 0x000000010a61943e __56-[UIPresentationController runTransitionForCurrentState]_block_invoke + 175
 6 UIKit 0x000000010a53997e _applyBlockToCFArrayCopiedToStack + 314
 7 UIKit 0x000000010a5397f8 _afterCACommitHandler + 516
 8 CoreFoundation 0x000000010bf88337 __CFRUNLOOP_IS_CALLING_OUT_TO_AN_OBSERVER_CALLBACK_FUNCTION__ + 23
 9 CoreFoundation 0x000000010bf88290 __CFRunLoopDoObservers + 368
 10 CoreFoundation 0x000000010bf7e0c3 __CFRunLoopRun + 1123
 11 CoreFoundation 0x000000010bf7d9f6 CFRunLoopRunSpecific + 470
 12 GraphicsServices 0x000000010e36f9f0 GSEventRunModal + 161
 13 UIKit 0x000000010a516990 UIApplicationMain + 1282
 14 Wrix 0x00000001075c95aa main + 106
 15 libdyld.dylib 0x000000010c984145 start + 1
 16 ??? 0x0000000000000001 0x0 + 1
 )
 libc++abi.dylib: terminating with uncaught exception of type NSException

 

「自爆機能」の解除方法

上記の「自爆機能」が発動するUIViewControllerの「自爆機能」を解除するには、UIViewController@presentViewControllerメソッドで表示する前に以下の事を行います。

  • UIViewController.popoverPresentationController.sourceView プロパティにUIViewを設定する

これだけだとPopoverの位置がおかしくなるかと思いますので、以下のプロパティで細かく場所を指定した方が良いでしょう。

  • UIViewController.popoverPresentationController.sourceRect

位置が表示領域の端の方にある場合、以下の様に最後に自分で突っ込みを入れた様な出力がされるかも知れません(笑)
この様な出力があった場合は表示されていないかと思いますので場所を微調整してください。

[AirDrop。近くの人と共有します。表示されない...']

 

上記の「自爆機能」が発動するUIViewControllerの内部的にはUIPopoverPresentationControllerクラスでPopoverを表示していると思いますが、以下の事も行った方が良いかも知れません。
※上記UIViewControllerは設定していなくても問題はありませんでした。内部で設定してるのかも知れません。

  • UIViewController.modalPresentationStyle プロパティにUIModalPresentationPopoverを設定する

なお、上記の「自爆機能」が発動するUIViewController以外にもUIDocumentInteractionControllerクラスも似ているのですが、そもそもUIViewControllerの子クラスではなく、表示用に以下の様にUIViewと場所を指定するメソッドが用意されていますので、こちらは間違いようが無いですね。

- (BOOL)presentOptionsMenuFromRect:(CGRect)rect
                             inView:(UIView *)view
                           animated:(BOOL)animated

 

まとめ

自爆機能の原因と解決方法を含めて詳細は理解して頂けましたでしょうか。
大変にわかりにくい所に潜んでいるため、ウチもかなり困りました。
この情報を元に多くの方に役に立てば幸いです。

iOS8向けアプリ開発時の注意点」にも書きましたが、iOS8は表示領域がおかしくなる問題が発生します。
他にも「画面の半分位のタッチ操作がOSの機能に奪われてしまう」という笑えない不具合もあります。
発生方法、サンプルコードを含めてAppleにはBugReportを提出済みですが、いつ直るのかはわかりません。
今の所、UINavigationControllerを使用してLandscapeにすると発生しやすいという所まではわかっていますが、内部的な処理の問題なのでAppleの修正待ちです。

何にしてもiOS8は開発者を大変困らせる改修が数多く行われたという事では無いかと思います。
もし、iOSアプリ開発などで私どもが協力できそうな事がありましたならばご連絡ください。
超強力な開発者が開発のご協力をさせて頂きます(笑)

iOS向けにスクラッチで開発した超高機能テキストエディタ「Wrix」もよろしくお願いします。

2014/09/21 This post was written by Categories: iOSiPhone Tagged with:
No comments yet



コメントを残す

メールアドレスが公開されることはありません。

*

Top