LoginSignup
0
1

More than 1 year has passed since last update.

UIActivityViewControllerで動画をシェアする

Last updated at Posted at 2021-09-07

Xcode Version 12.5.1

カメラロール内の動画をUIActivityViewControllerでシェアできるようにしました。
3日詰まりました。。

mojikyo45_640-2.gif

ImageはこんなかんじでactivityItemsにそのまま渡してやれば良いので、簡単です。

import SwiftUI
import PhotosUI //忘れずに

struct ImageShareSheet: UIViewControllerRepresentable {
    @State var image: UIImage

    func makeUIViewController(context: Context) -> UIActivityViewController {
        let text = "Image"
        let activityItems: [Any] = [image, text]
        let controller = UIActivityViewController(
            activityItems: activityItems,
            applicationActivities: nil)
        return controller
    }

    func updateUIViewController(_ vc: UIActivityViewController, context: Context) {
    }
}

問題は動画です。
動画はURLで渡すのですが、そのまま渡すと「サンドボックス拡張機能の発行に失敗しました」というようなエラーが出ました。
私は元ファイルのURLを@StateでStringで受けとって使用していましたが、なんだろう、揮発するのかな?上手くいきませんでした。
正確に言うと、AirDropとMessageアプリでは送れるのに、メールやLINEで送れませんでした。(写真は送れたけど動画が送れず)

元になるPHAssetファイルのURLをstruct MovieShareSheet内で改めて取得し、fileManager.copyItemでTempディレクトリにコピーしてから、コピーしたファイルに対して操作を実行することで、うまく行くようになりました。やったー!

struct MovieShareSheet: UIViewControllerRepresentable {
    @State var photo: PHAsset

    func makeURLandCopy() -> URL {
        let fileURL = photo.getURL(ofPhotoWith: photo)
        print("fileURL(元): \(String(describing: fileURL))")
        let temporaryDirectoryURL = URL(fileURLWithPath: NSTemporaryDirectory(), isDirectory: true)
        let temporaryFileURL = temporaryDirectoryURL.appendingPathComponent(fileURL!.lastPathComponent)
        print("temporaryFileURL(コピー先):\(temporaryFileURL)")
        copyToTmp(fileURL: fileURL!, temporaryFileURL: temporaryFileURL)
        return temporaryFileURL
    }

    func copyToTmp(fileURL: URL, temporaryFileURL: URL){
        let fileManager = FileManager.default
        do{try fileManager.copyItem(at: fileURL, to: temporaryFileURL)}
        catch{}
        return
    }


    func makeUIViewController(context: Context) -> UIActivityViewController {
        let fileURL = makeURLandCopy()
        let activityItems: [Any] = [fileURL]
        let controller = UIActivityViewController(
            activityItems: activityItems,
            applicationActivities: nil)
        return controller
    }

    func updateUIViewController(_ vc: UIActivityViewController, context: Context) {
    }
}

extension PHAsset{
    func getURL(ofPhotoWith mPhasset: PHAsset) -> URL?{
        var url = URL(string:"test")
        let semaphore = DispatchSemaphore(value: 0)
        let options=PHVideoRequestOptions()

        options.version = .current
        options.isNetworkAccessAllowed = true
        PHImageManager.default().requestAVAsset(forVideo: mPhasset,                                                 options: options)
        {(asset:AVAsset?,audioMix, info:[AnyHashable:Any]?) -> Void in

            if let urlAsset = asset as? AVURLAsset{
                let localURL = urlAsset.url as URL
                url = localURL
                print(url!)
            }else{
                print("url asset nil")
            }
            do   {semaphore.signal() }
        }
        if semaphore.wait(timeout: DispatchTime.distantFuture) == .success {
            print("url success")
            return url!
        }else{
            print("url timeout")
            return url!
        }
    }

}


(Tmpファイルは自分で消さなくて大丈夫なのかな…?気になっています)
お役に立てれば幸いです!
もっと良い美しい方法があればぜひご教示ください!

参考
https://try2explore.com/questions/12413739
https://stackoverflow.com/questions/57798968/didfinishpickingmediawithinfo-returns-different-url-in-ios-13

0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1