Sponsor Link
環境&対象
- macOS Monterey 12.4 beta2
- Xcode 13.3.1
- iOS 15.4
UIActivityViewController
UIActivityViewController は、iOS 上で、以下のような共有シートを表示して、渡したデータを 別のアプリ等に渡すことができるようにしてくれる ViewController です。
Apple のドキュメントは、こちら。
SwiftUI に同機能の View は用意されていないため、SwiftUI で使うためには、UIViewControllerRepresentable を使用して、wrap して使う必要があります。
Readme をアップデートできていませんが、Github に SDSSharingServicePicker として、サンプルをあげています。
activityItems
UIActivityViewController は、activityItems 引数に要素を指定して呼び出すことで、指定した要素を共有対象として、引き渡し先のアプリ選択を行うことができるようになっています。
UIImage や String を渡すとそのままで渡されますので、特に難しいところはありません。
activityItems にURL を渡す
一旦ファイルに書き出したデータについて、共有しようとしたときに問題が発生しました。
データは以下のようにして、テンポラリディレクトリに書き出していました。
let tmpFile: URL = URL(fileURLWithPath: "WeightClip.csv", relativeTo: FileManager.default.temporaryDirectory)
let data = viewModel.csvData()
try? data.write(to: tmpFile)
上記のコードでテストしてみたところ、Files (ファイル)アプリへ渡して保存すると期待通りに動きます。
ファイルの中身も期待通りになっています。
ところが、AirDrop を使って渡すと 以下のような内容のファイルになりました。
渡そうとしたデータは CSV で複数行のテキストなのですが、渡されてきたファイルには、2行しかなく、パスっぽいものしか書かれていません。書いてあるパス自体は正しそうなのですが、パスを渡したかったわけではありません・・・
ファイル(Files)アプリには、ファイルの内容がパスではなくファイルの内容がセットされていたので、URL を渡すことが間違いではなさそうです・・・・
色々と試して、解決策を見つけました。
URL が相対パスのままでは渡せない
どうやら、URL を共有するときには、相対パスではなく絶対パスにして渡す必要があるようです。
厳密には、いくつかの共有対象には、相対パスではなく絶対パスが必要ということのようです。
つまり、activityItems には、以下のように、絶対パスに変換してから渡すことが必要でした。
// 相対パスで設定
var tmpFile: URL = URL(fileURLWithPath: "WeightClip.csv", relativeTo: FileManager.default.temporaryDirectory)
tmpFile // - 相対パスのまま
tmpFile.absoluteURL // - 絶対パスに変換
どの 共有対象(activityType) が相対パスで OK で、どの共有対象が絶対パスに変換する必要があるかの詳細は確認していません。
絶対パスで渡すことでのデメリットはないと思いますので、絶対パスに変換して渡してしまうのが良いと思います。
この制約は、Apple のドキュメントのどこかに書いてあるのかもしれませんが、見つけられませんでした。
まとめ
UIActivityViewController の AirDrop 経由で ファイルをうまく渡せないケースの解決方法を説明しました。
- UIActivityViewController での activityItems に URL を渡すときは絶対パスに変換する
説明は以上です。
不明な点やおかしな点ありましたら、こちらまで。
Sponsor Link