【SwiftUI】iPadでUIActivityViewControllerがクラッシュする解決法!

この記事からわかること
- SwiftのUIActivityViewControllerの注意点と使い方
- iPadでクラッシュする原因と解決方法
- UIPopoverPresentationControllerクラスとpopoverPresentationControllerプロパティ
- sourceView/barButtonItem/sourceItem/sourceRect
index
[open]
\ アプリをリリースしました /
SwiftでiOSアプリを開発中にUIActivityViewControllerを使ってシェアボタンを実装していたところ、iPadでシミュレーションするとクラッシュしてしまいました。この原因と解決方法をまとめていきたいと思います。
UIActivityViewControllerがクラッシュする問題
Swift UIを使ったアプリにUIActivityViewController
を使ってシェアボタンを実装していた際にiPhoneのシミュレーションでは正常に動作したのですがiPadのシミュレーションだとクラッシュしてエラーが発生してしまいました。
シェアボタンの実装コード
クラッシュ後に発生したエラー
原因と解決方法
原因はiPadの場合、シェアUIのようなポップオーバー画面を表示させる際はビューと表示位置を明示的に指定する必要があるようです。指定されていない場合はランタイムエラーとなり、エラーを吐いてしまうようです。
解決するにはエラーの内容に従いsourceView
を追加していきます。私はSwiftUIでビューを構築していたので同じ境遇の人の参考になると幸いです。
表示させるビューの指定と表示位置の指定はUIPopoverPresentationController
クラスのプロパティにセットする必要があります。先に全体のコードを載せておきます。
解決コード
UIPopoverPresentationControllerクラス
UIPopoverPresentationController
クラスはポップオーバーの表示に関する操作を管理するクラスです。このクラスをインスタンス化するためにはUIActivityViewController
クラスのpopoverPresentationController
プロパティを使用します。
このプロパティは正確にはUIActivityViewController
クラスが準拠しているUIViewController
クラスのプロパティで、ポップオーバービューがあればそのオブジェクトが格納され、なければnil
が格納されます。
nil
の可能性があるのでオプショナルバインディングでインスタンスを変数に格納します。
これでオブジェクトに参照できるようになったので各プロパティに値をセットしていきます。
sourceViewプロパティ
sourceView
はポップオーバーを表示させるアンカー(支え)となるビューを指定するプロパティです。
格納するのはUIActivityViewController
のview
プロパティです。これも正確には準拠しているUIViewController
クラスのプロパティでコントローラが管理しているビューがここに格納されています。つまりここではアクティブなっているビューを示しています。
barButtonItemプロパティ
barButtonItem
は指定したバーボタンにポップオーバーを固定するプロパティです。指定するとポップオーバーの矢印は指定された項目を指すような見た目になります。ですがiOS 8.0–16.0 Deprecated:非推奨になっており、ゆくゆくはsourceItem
に変わっていくようですがこちらはまだベータ版なので注意が必要です。
一応コードを示しておきます。今回は特に指し示す項目を指定しないので.none
を渡します。
sourceRectプロパティ
sourceRect
はポップオーバーを固定するソースビュー内の領域を指定するプロパティです。格納する値は四角形領域の位置と寸法を定義するCGRect
型で指定します。
今回sourceRect
に指定したいのは位置(座標)部分を示すx
とy
です。位置情報には使用しているデバイス(画面)のサイズをUIScreen.main.bounds
で取得して指定します。
デバイスを識別してiPadの時のみ実行させる
最後に実行されているデバイスを識別し、iPadの時のみ処理を実行させるようにしていきます。先ほどの処理を囲うようにUIDevice.current.userInterfaceIdiom == .pad
を使ってiPadかどうかで分岐できるようにしておきます。
これで無事SwiftUIでシェアボタンを作成した際にiPadでクラッシュしないようにすることができました。
iPadでシェアボタンが動作しない
追記:2022/9/14
上記の方法で使用できていたシェアボタンが突然使用できなくなってしまいました。発生していたエラー内容は以下の通りです。
上記のエラー内容をみてもよくわかりませんでした。なかなか不親切ですね。。もう1つそれっぽいエラーが出ていました。
解決の糸口が少し見えた気がします。つまりUICollectionView
の何かしらのプロパティに対しての変更が許容されていないようです。
模索してみたところsourceRect
プロパティへのCGRectを使っての指定が原因 のようです。とりあえずaccessibilityFrame
プロパティをそのまま指定することで無事表示させることはできましたが、表示位置が左上部になってしまいしました。また良い方法があれば追記しておきます。
まだまだ勉強中ですので間違っている点や至らぬ点がありましたら教えていただけると助かります。
ご覧いただきありがとうございました。
私がSwift UI学習に使用した参考書