我有一个带有多个控制器的音频应用程序,VCMain 控制器显示所有书籍和 VCBook 控制器,其中有下载音频文件的功能(书籍可以有很多文件(。
单击下载按钮时会出现一个圆形进度条。
当我返回VCMain并返回下载的书籍时,我拥有进度条设置的所有必要数据(哪些书籍仍在下载或正在下载(。我可以同时下载几本书
var progressIndicatorView:CircularProgressView!
lazy var sizeBytes:Int64 = 0
lazy var dowloandedSizeBytes:Int64 = 0
@objc func progressBar(){
DispatchQueue.main.async {
self.progressIndicatorView = CircularProgressView(frame: CGRect(x: 5, y: -20, width: 50, height: 50))
self.view.addSubview(self.progressIndicatorView)
self.download.isEnabled = false
self.download.isHidden = true
}
}
@objc func downloadBook(){
progressBar()
for i in UrlName{
Func.getDownloadSize(url: URL(string: i)!, completion: { [weak self] (size, error) in
self!.sizeBytes += size
})
if let audioUrl = URL(string: i) {
// create your document folder url
let documentsUrl = try! FileManager.default.url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: true)
// your destination file url
let destination = documentsUrl.appendingPathComponent(audioUrl.lastPathComponent)
// check if it exists before downloading it
if FileManager().fileExists(atPath: destination.path) {
print("The file already exists at path")
bookMarkLoad()
Func.getDownloadSize(url: URL(string: i)!, completion: { [weak self] (size, error) in
self!.dowloandedSizeBytes += size
})
} else {
// if the file doesn't exist
// just download the data from your url
var url = URLRequest(url: audioUrl)
url.timeoutInterval = Double.infinity
let config = URLSessionConfiguration.background(withIdentifier: i)
let session = URLSession(configuration: config, delegate: self, delegateQueue: nil)
let task = session.downloadTask(with: url)
task.taskDescription = String(format:"%@" , i )
task.resume()
registerBackgroundTask()
// let _ = Timer.scheduledTimer(timeInterval: 0.5, target: self, selector: #selector(backgraundState), userInfo: nil, repeats: true)
}
}
}
}
func urlSession(_ session: URLSession, downloadTask: URLSessionDownloadTask, didWriteData bytesWritten: Int64, totalBytesWritten: Int64, totalBytesExpectedToWrite: Int64) {
if UrlName.contains(downloadTask.taskDescription!){
if totalBytesExpectedToWrite > 0 {
dowloandedSizeBytes += bytesWritten
let progress = Float(dowloandedSizeBytes) / Float(sizeBytes)
// print("Progress (downloadTask) (progress)")
DispatchQueue.main.async {
if self.progressIndicatorView != nil {
self.progressIndicatorView.progress = CGFloat(progress)
}
}
}
}
}
这是一个相当广泛的问题,但我建议首先将与下载相关的所有逻辑移动到单独的服务。使此类逻辑远离视图/视图控制器被认为是一种很好的做法。
此服务将负责处理下载,并可以通知应用程序的其他部分(例如视图控制器(进度,例如通过使用通知。
然后,MainVC 可以从服务请求状态信息并更新视图,例如在viewWillAppear(_:)
方法中。
有关如何开始构建应用和服务的一些示例,请访问:
- https://www.raywenderlich.com/477-design-patterns-on-ios-using-swift-part-1-2
- https://medium.com/ios-os-x-development/pluggableapplicationdelegate-e50b2c5d97dd
- https://medium.com/@johnsundell/avoiding-singletons-in-swift-5b8412153f9b