[Swift][iOS] UIActivityViewController で ファイルを URL を使って共有する方法

UIKit

     

TAGS:

UIActivityViewController の AirDrop 経由で ファイルをうまく渡せないケースの解決方法を説明します。

環境&対象

以下の環境で動作確認を行なっています。

  • macOS Monterey 12.4 beta2
  • Xcode 13.3.1
  • iOS 15.4

UIActivityViewController

UIActivityViewController は、iOS 上で、以下のような共有シートを表示して、渡したデータを 別のアプリ等に渡すことができるようにしてくれる ViewController です。

Apple のドキュメントは、こちら

ShareSheet

SwiftUI に同機能の View は用意されていないため、SwiftUI で使うためには、UIViewControllerRepresentable を使用して、wrap して使う必要があります。

MEMO
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 を使って渡すと 以下のような内容のファイルになりました。

FileFromAirDrop

渡そうとしたデータは CSV で複数行のテキストなのですが、渡されてきたファイルには、2行しかなく、パスっぽいものしか書かれていません。書いてあるパス自体は正しそうなのですが、パスを渡したかったわけではありません・・・

ファイル(Files)アプリには、ファイルの内容がパスではなくファイルの内容がセットされていたので、URL を渡すことが間違いではなさそうです・・・・

色々と試して、解決策を見つけました。

URL が相対パスのままでは渡せない

どうやら、URL を共有するときには、相対パスではなく絶対パスにして渡す必要があるようです。

厳密には、いくつかの共有対象には、相対パスではなく絶対パスが必要ということのようです。

つまり、activityItems には、以下のように、絶対パスに変換してから渡すことが必要でした。


// 相対パスで設定
var tmpFile: URL = URL(fileURLWithPath: "WeightClip.csv", relativeTo: FileManager.default.temporaryDirectory)
tmpFile // - 相対パスのまま
tmpFile.absoluteURL // - 絶対パスに変換
MEMO
どの 共有対象(activityType) が相対パスで OK で、どの共有対象が絶対パスに変換する必要があるかの詳細は確認していません。
絶対パスで渡すことでのデメリットはないと思いますので、絶対パスに変換して渡してしまうのが良いと思います。
MEMO
この制約は、Apple のドキュメントのどこかに書いてあるのかもしれませんが、見つけられませんでした。

まとめ

UIActivityViewController の AirDrop 経由で ファイルをうまく渡せないケースの解決方法を説明しました。

UIActivityViewController の AirDrop 経由で ファイルをうまく渡せないケースの解決方法
  • UIActivityViewController での activityItems に URL を渡すときは絶対パスに変換する

説明は以上です。
不明な点やおかしな点ありましたら、こちらまで。

コメントを残す

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