下载列表功能简单实现

199 阅读1分钟
  • 歌曲搜索网络请求
class Service {
    
    static let shared = Service()
    
    /// 搜索歌曲网络请求
    func queryMusicList(musicTitle:String,completion:@escaping((_ musics:[Any])->())) {
        
        let urlString = "https://itunes.apple.com/search?media=music&entity=song&term=\(musicTitle)"
        guard let url = URL(string: urlString) else { return }
        let request = URLRequest(url: url, cachePolicy: .reloadIgnoringLocalCacheData, timeoutInterval: 30)
        let session = URLSession.shared
        let task = session.dataTask(with: request) { data, response, error in
            guard error == nil else {
                debugPrint(error?.localizedDescription ?? "")
                return
            }
            guard let data = data else {
                debugPrint("数据有误")
                return
            }
            do {
                guard let dictionary = try JSONSerialization.jsonObject(with: data, options: .mutableContainers) as? [String:Any] else { return }
                guard let results = dictionary["results"] as? [Any] else { return }
                DispatchQueue.main.async {
                    completion(results)
                }
            } catch {
                debugPrint("解析失败")
            }
        }
        task.resume()
        
    }
    
}
  • 歌曲模型
enum DownLoadState {
    case unDownload // 未下载
    case Donwloading // 正在下载
    case Downloaded // 下载完成
}

struct MusicModel:HandyJSON {
    var trackName = ""
    var artistName = ""
    var previewUrl = ""
    
    var index = 0
    var progress:Float = 0.0
    var downloadState = DownLoadState.unDownload
}
  • 记录当前正在下载的模型
var activityDownload = [URL:MusicModel]()
  • 开始下载
fileprivate func startDownloadMusic(model:MusicModel) {
    
    let index = model.index
    var music = self.dataList[index]
    music.downloadState = .Donwloading
    self.dataList[index] = music
        
    guard let url = URL(string: model.previewUrl) else { return }
    let request = URLRequest(url: url)
    let config = URLSessionConfiguration.default
    let session = URLSession(configuration: config, delegate: self, delegateQueue: nil)
    let task = session.downloadTask(with: request)
        
    // 将当前下载的数据记录下来
    activityDownload[url] = music
        
    task.resume()    
}
  • URLSessionDownloadDelegate
extension ViewController:URLSessionDownloadDelegate {
    // 下载完成后
    func urlSession(_ session: URLSession, downloadTask: URLSessionDownloadTask, didFinishDownloadingTo location: URL) {
        
        let locationPath = location.path
        let fileName = downloadTask.response?.suggestedFilename ?? ""
        guard locationPath != "", fileName != "" else { return }
        let musicPath = NSHomeDirectory() + "/Library/Caches/Download/Music"
        let filePath = musicPath + "/" + fileName
        do {
            if FileManager.default.fileExists(atPath: musicPath) == false {
                try FileManager.default.createDirectory(atPath: musicPath, withIntermediateDirectories: true)
            }
            try FileManager.default.moveItem(atPath: locationPath, toPath: filePath)
        } catch let catchError {
            debugPrint("保存出错 = \(catchError.localizedDescription)")
            return
        }
        
        debugPrint("下载完成")
        guard let url = downloadTask.originalRequest?.url,
              var model = self.activityDownload[url] else { return }
        let index = model.index
        model.downloadState = .Downloaded
        self.dataList[index] = model
        // 下载完成后刷新当前单元格
        DispatchQueue.main.async {[weak self] in
            self?.mainTableView.reloadRows(at: [IndexPath(row: index, section: 0)], with: .automatic)
        }
        
    }

    // 下载进度
    func urlSession(_ session: URLSession, downloadTask: URLSessionDownloadTask, didWriteData bytesWritten: Int64, totalBytesWritten: Int64, totalBytesExpectedToWrite: Int64) {
        let progress = Float(totalBytesWritten) / Float(totalBytesExpectedToWrite)
        
        guard let url = downloadTask.originalRequest?.url,
              var model = self.activityDownload[url] else { return }
        let index = model.index
        model.progress = progress
        self.dataList[index] = model
        
        // 主线程刷新下载进度
        DispatchQueue.main.async {[weak self] in
            guard let cell = self?.mainTableView.cellForRow(at: IndexPath(row: index, section: 0)) as? MusicCell else { return }
            cell.updateProgress(progress: progress)
        }
    }

    // 回复下载的代理方法
    func urlSession(_ session: URLSession, downloadTask: URLSessionDownloadTask, didResumeAtOffset fileOffset: Int64, expectedTotalBytes: Int64) {
        debugPrint("恢复下载")
    }
}