はじめに
こんにちは、nukkyです。
私は普段iPhoneアプリの開発を主に行っているのですが
慣れか油断かiPadでの確認をおろそかにしてしまい、
クラッシュバグの存在に長い間気づかないでいたので
戒めつつ備忘録としてここに残したいと思います。
エラー内容
エラー原因
まずはサンプルコード
ボタンをタップしたらUIAlertControllerで
ActionSheetを表示するサンプルです。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | @IBAction func showAlert(_ sender: Any) { let actionSheet = UIAlertController(title: "タイトル", message: "メッセージ", preferredStyle: UIAlertControllerStyle.actionSheet) let action1 = UIAlertAction(title: "アクション1", style: UIAlertActionStyle.default, handler: { (action: UIAlertAction!) in }) let action2 = UIAlertAction(title: "アクション2", style: UIAlertActionStyle.default, handler: { (action: UIAlertAction!) in }) let action3 = UIAlertAction(title: "アクション3", style: UIAlertActionStyle.destructive, handler: { (action: UIAlertAction!) in }) let cancel = UIAlertAction(title: "キャンセル", style: UIAlertActionStyle.cancel, handler: { (action: UIAlertAction!) in }) actionSheet.addAction(action1) actionSheet.addAction(action2) actionSheet.addAction(action3) actionSheet.addAction(cancel) self.present(actionSheet, animated: true, completion: nil) } |
このソースを実行するとiPhoneでは問題なく表示されますが
iPadで実行すると以下のクラッシュ発生してしまいます。。。
1 2 3 4 5 6 7 8 | Terminating app due to uncaught exception 'NSGenericException', reason: 'Your application has presented a UIAlertController (<UIAlertController: 0x7f80fb418ae0>) of style UIAlertControllerStyleActionSheet. The modalPresentationStyle of a UIAlertController with this style is UIModalPresentationPopover. You must provide location information for this popover through the alert controller's popoverPresentationController. You must provide either a sourceView and sourceRect or a barButtonItem. If this information is not known when you present the alert controller, you may provide it in the UIPopoverPresentationControllerDelegate method -prepareForPopoverPresentation.' |
結論を述べると、
UIAlertControllerでActionSheetを表示する際に
popoverPresentationControllerの
sourceViewを指定しないとクラッシュします!!!
というわけで上記ソースを少し修正。
1 2 3 4 5 6 7 8 | actionSheet.addAction(action1) actionSheet.addAction(action2) actionSheet.addAction(action3) actionSheet.addAction(cancel) // iPadでは必須! actionSheet.popoverPresentationController?.sourceView = self.view self.present(actionSheet, animated: true, completion: nil) |
この一文を加えることでクラッシュを回避できます。
まだこれで解決ではない
上記の対応によりクラッシュは回避できましたが、
このままiPadで実行すると以下の様な表示になります。
このままだと不恰好なので、
ActionSheetの表示位置を調整します。
1 2 3 4 5 6 7 | actionSheet.popoverPresentationController?.sourceView = self.view let screenSize = UIScreen.main.bounds // ここで表示位置を調整 // xは画面中央、yは画面下部になる様に指定 actionSheet.popoverPresentationController?.sourceRect = CGRect(x: screenSize.size.width/2, y: screenSize.size.height, width: 0, height: 0) self.present(actionSheet, animated: true, completion: nil) |
ちなみに、popoverPresentationControllerの
sourceRectですが、iPhoneで表示する際には全く影響がないので
iPad用に処理を分ける必要はないです。
さいごに
確認すれば、すぐに発生する不具合に
長いこと気づかず、本当に恥ずかしかったです、、、
今回に限った話ではないですが何事も確認というものは改めて大事だと思いました。
そういう思いで書いた、この記事が誰かのお役にたてれば嬉しいです。
そうです!2018年4月17日時点まだ直されないです!
助かりました!