Search code examples
iosobjective-cswiftalamofirebackground-process

Video download using Alamofire is freezing the UI in Swift iOS


I am developing a Video editing Application in Swift. I am downloading video clips with Progress.

My problem is when I am downloading the video using Alamofire then this freezes my UI until the process will get complete. Here is my code:

    //MARK: -  Download Video file
    func downloadVideoFileFromUrl(videoUrl: URL, video: VideoFileModel) {

        var uniqueVideoID = ""
        var uniqueID = ""

        uniqueID = video.fileID

        uniqueVideoID = uniqueID  + ".MOV"

        let destination: DownloadRequest.DownloadFileDestination = { _, _ in
            var documentsURL = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0]

            // the name of the file here I kept is yourFileName with appended extension
            documentsURL.appendPathComponent(uniqueVideoID)
            return (documentsURL, [.removePreviousFile])
        }

        var vidProgress: Float = 0.0


        let manager = Alamofire.SessionManager.default
        manager.session.configuration.timeoutIntervalForRequest = 900
        manager.session.configuration.timeoutIntervalForResource = 900

        manager.download(videoUrl, to:destination)
            .downloadProgress { (progress) in

                DispatchQueue.main.async(execute: {

                    vidProgress = Float(progress.fractionCompleted)
                    video.downloadFromUrlProgress = vidProgress

                    //post notification
                    let userInfo = [ "videoFileModel" : video]
                    NotificationCenter.default.post(name: Notification.Name(rawValue: "VideoDownloadProgress"), object: nil, userInfo: userInfo)

                })

            }
            .response { defaultDownloadResponse in

                DispatchQueue.main.async(execute: {

                    print(defaultDownloadResponse.destinationURL as Any)

                    if defaultDownloadResponse.destinationURL != nil{
                        video.localFilePath = (defaultDownloadResponse.destinationURL?.absoluteString)!
                        video.downloadFromUrlProgress = 1
                        video.isVideoDownload = true

                        let userInfo = [ "videoFileModel" : video]
                        NotificationCenter.default.post(name: Notification.Name(rawValue: "VideoDownloadProgress"), object: nil, userInfo: userInfo)
                        print("Completed!")

                    }

                })
        }
    }

I am calling this method using

DispatchQueue.global(qos: .userInitiated).sync { }

Can anyone help me how can I resolve this issue?


Solution

  • Try using below code:

    func download(url: String,fileName: String,progressUpdate: ((_ percent: Double) -> Void)? = nil, completion:@escaping (_ success: Bool, _ error: Error?,_ fileUrl: URL?) -> Void) {
            let utilityQueue = DispatchQueue.global(qos: .utility)
            Alamofire.download(url)
                .downloadProgress(queue: utilityQueue) { progress in
                    DispatchQueue.main.async {
                        progressUpdate?(progress.fractionCompleted)
                    }
                }
                .responseData { response in
                    if let data = response.result.value {
                        let fileURL = try! FileManager.default.url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: false).appendingPathComponent(fileName)
                        do {
                            try data.write(to: fileURL, options: .atomic)
                            completion(true,nil,fileURL)
                        } catch {
                            completion(false,error,nil)
                        }
                    }
            }
    
        }
    

    How to use it:

    download(url: "", fileName: "filName", progressUpdate: { (progress) in
                print("Progress \(progress)")
            }) { (success, error, filePath) in
                print("success \(success) error \(error?.localizedDescription ?? "nil") path \(filePath?.absoluteString ?? "nil")")
            }