SwiftUI | 動画や画像をダウンロードする方法

音声・動画

SwiftUIで動画や画像をダウンロードする方法を説明する。

結論

ダウンローダーのモデルとなるclass(中身はある程度決まった型のコード)を定義し、ContentViewで使う。

具体例

入力したURLの動画や画像をダウンロードしプレビュー表示するAppを例に説明する。

ダウンローダーのモデルとなるclass ダウンローダーのモデル を定義する

import SwiftUI

class ダウンローダーのモデル: NSObject,
                    ObservableObject,
                    URLSessionDownloadDelegate,
                    UIDocumentInteractionControllerDelegate {    
    @Published var ダウンロードと保存をするタスク: URLSessionDownloadTask!
    @Published var ダウンロード進捗率: Int = 0
    
    // ■ 1 ダウンロード開始
    func ダウンロード開始(アドレス: String) {
        guard let 有効アドレス = URL(string: アドレス) else {
            print("URLが無効")
            return
        }
        ダウンロード進捗率 = 0
        let セッション = URLSession(configuration: .default,
                               delegate: self,
                               delegateQueue: nil)
        ダウンロードと保存をするタスク = セッション.downloadTask(with: 有効アドレス)
        ダウンロードと保存をするタスク.resume()  // ダウンロード開始
        print("ダウンロード開始")
    }

    // ■ 2 ダウンロード中(ダウンロード中は自動的に実行)
    func urlSession(_ session: URLSession,
                    downloadTask: URLSessionDownloadTask,
                    didWriteData bytesWritten: Int64,
                    totalBytesWritten: Int64,
                    totalBytesExpectedToWrite: Int64) {
        let ダウンロードできたサイズ = Float(totalBytesWritten)
        let トータルサイズ = Float(totalBytesExpectedToWrite)
        let 進捗率 = Int(round(ダウンロードできたサイズ / トータルサイズ * 100))
        
        // URLセッションはバックグラウンドスレッドで実行されるので
        // UIのアップデートに関する処理はメインスレッドで実行
        DispatchQueue.main.async {
            self.ダウンロード進捗率 = 進捗率
        }
    }
    
    // ■ 3 ダウンロード完了(ダウンロード完了時に自動的に実行)
    func urlSession(_ session: URLSession,
                    downloadTask: URLSessionDownloadTask,
                    didFinishDownloadingTo location: URL) {
        print("ダウンロード完了")
        guard let リクエストのURL = downloadTask.originalRequest?.url else {
            print("リクエストのURLエラー")
            return
        }
        let ファイル名 = リクエストのURL.lastPathComponent
        let 一時ファイルパス = location
        let 最終パス = FileManager.default.urls(for: .documentDirectory,
                                            in: .userDomainMask)[0]
        let 最終ファイルパス = 最終パス.appendingPathComponent(ファイル名)
        print(最終ファイルパス)
        try? FileManager.default.removeItem(at: 最終ファイルパス)
        
        do {
            try FileManager.default.copyItem(at: 一時ファイルパス, to: 最終ファイルパス)
            print("ファイル保存完了")
            DispatchQueue.main.async {
                // ■ 3 -> 4 ダウンロードしたファイルをプレビュー表示
                print("プレビューします")
                let controller = UIDocumentInteractionController(url: 最終ファイルパス)
                controller.delegate = self
                controller.presentPreview(animated: true)
            }
        } catch {
            print("ファイルコピーでエラー")
        }

    }
    
    // ■ 4 プレビュー(ダウンロードしたファイルをプレビュー)
    func documentInteractionControllerViewControllerForPreview(
        _ controller: UIDocumentInteractionController) -> UIViewController {
        let scenes = UIApplication.shared.connectedScenes
        let windowScenes = scenes.first as? UIWindowScene
        let window = windowScenes?.windows.first
        return window!.rootViewController!
    }

    // ■ 5 エラー出力(ダウンロード完了時に自動的に実行)
    func urlSession(_ session: URLSession,
                    task: URLSessionTask,
                    didCompleteWithError error: Error?) {
        if let error = error {
            print("エラー有り")
            print(error)
            return
        } else {
            print("エラー無し")
        }
    }
     
}

ContentViewでこのclassのインスタンスを作成して使う。

import SwiftUI

struct ContentView: View {
    @StateObject var ダウンローダー = ダウンローダーのモデル()
    @State var url = "https://swiftui.kazunoriri.com/wp-content/uploads/2022/08/rika_movie.mp4"    
    var body: some View {
            VStack {
                TextField("URL", text: $url)
                    .padding()
                    .background(Color(red: 0.95, green: 0.95, blue: 0.95))
                Button("ダウンロード") {
                    ダウンローダー.ダウンロード開始(アドレス: url)
                }
                .buttonStyle(.borderedProminent)
                .padding()
                Text(String(ダウンローダー.ダウンロード進捗率) + "%")
            }
            .padding()
    }
}

完成。以下にAppの動作をGIF動画で示す。

Appの完成イメージGIF動画

まとめ

SwiftUIで動画や画像をダウンロードする方法を説明した。

コメント

タイトルとURLをコピーしました