From 5a8e57434ea4ac2400daca47e3bdfcd90870701e Mon Sep 17 00:00:00 2001 From: SunCJ Date: Wed, 7 Nov 2018 18:07:06 +0800 Subject: [PATCH 1/5] chore: avoid (X / 0) crash --- MZDownloadManager/Classes/MZDownloadManager.swift | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/MZDownloadManager/Classes/MZDownloadManager.swift b/MZDownloadManager/Classes/MZDownloadManager.swift index 6a539fe..560b832 100644 --- a/MZDownloadManager/Classes/MZDownloadManager.swift +++ b/MZDownloadManager/Classes/MZDownloadManager.swift @@ -172,15 +172,18 @@ extension MZDownloadManager: URLSessionDownloadDelegate { for (index, downloadModel) in self.downloadingArray.enumerated() { if downloadTask.isEqual(downloadModel.task) { DispatchQueue.main.async(execute: { () -> Void in - - let receivedBytesCount = Double(downloadTask.countOfBytesReceived) - let totalBytesCount = Double(downloadTask.countOfBytesExpectedToReceive) - let progress = Float(receivedBytesCount / totalBytesCount) - let taskStartedDate = downloadModel.startTime ?? Date() let timeInterval = taskStartedDate.timeIntervalSinceNow let downloadTime = TimeInterval(-1 * timeInterval) + + let receivedBytesCount = Double(downloadTask.countOfBytesReceived) + let totalBytesCount = Double(downloadTask.countOfBytesExpectedToReceive) + guard totalBytesWritten == 0 || downloadTime == 0 else { + return + } + + let progress = Float(receivedBytesCount / totalBytesCount) let speed = Float(totalBytesWritten) / Float(downloadTime) let remainingContentLength = totalBytesExpectedToWrite - totalBytesWritten From dc782fc8569fdc82192cfb668c03f3526beb81a9 Mon Sep 17 00:00:00 2001 From: SunCJ Date: Wed, 7 Nov 2018 18:38:07 +0800 Subject: [PATCH 2/5] chrore: error guard --- MZDownloadManager/Classes/MZDownloadManager.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MZDownloadManager/Classes/MZDownloadManager.swift b/MZDownloadManager/Classes/MZDownloadManager.swift index 560b832..7221f8b 100644 --- a/MZDownloadManager/Classes/MZDownloadManager.swift +++ b/MZDownloadManager/Classes/MZDownloadManager.swift @@ -179,7 +179,7 @@ extension MZDownloadManager: URLSessionDownloadDelegate { let receivedBytesCount = Double(downloadTask.countOfBytesReceived) let totalBytesCount = Double(downloadTask.countOfBytesExpectedToReceive) - guard totalBytesWritten == 0 || downloadTime == 0 else { + guard totalBytesWritten != 0 && downloadTime != 0 else { return } From 1654af93199f2186768bee3d29bed925f64c9c8a Mon Sep 17 00:00:00 2001 From: SunCJ Date: Thu, 8 Nov 2018 18:19:40 +0800 Subject: [PATCH 3/5] chore: add fished task when background, safe self --- .../Classes/MZDownloadManager.swift | 53 ++++++++++--------- 1 file changed, 29 insertions(+), 24 deletions(-) diff --git a/MZDownloadManager/Classes/MZDownloadManager.swift b/MZDownloadManager/Classes/MZDownloadManager.swift index 7221f8b..c4f7da0 100644 --- a/MZDownloadManager/Classes/MZDownloadManager.swift +++ b/MZDownloadManager/Classes/MZDownloadManager.swift @@ -8,23 +8,23 @@ import UIKit fileprivate func < (lhs: T?, rhs: T?) -> Bool { - switch (lhs, rhs) { - case let (l?, r?): - return l < r - case (nil, _?): - return true - default: - return false - } + switch (lhs, rhs) { + case let (l?, r?): + return l < r + case (nil, _?): + return true + default: + return false + } } fileprivate func > (lhs: T?, rhs: T?) -> Bool { - switch (lhs, rhs) { - case let (l?, r?): - return l > r - default: - return rhs < lhs - } + switch (lhs, rhs) { + case let (l?, r?): + return l > r + default: + return rhs < lhs + } } @@ -75,7 +75,7 @@ open class MZDownloadManager: NSObject { fileprivate weak var delegate: MZDownloadManagerDelegate? open var downloadingArray: [MZDownloadModel] = [] - + public convenience init(session sessionIdentifer: String, delegate: MZDownloadManagerDelegate, sessionConfiguration: URLSessionConfiguration? = nil, completion: (() -> Void)? = nil) { self.init() self.delegate = delegate @@ -135,6 +135,9 @@ extension MZDownloadManager { } else if(downloadTask.state == .suspended) { downloadModel.status = TaskStatus.paused.description() downloadingArray.append(downloadModel) + } else if(downloadTask.state == .completed) { + downloadModel.status = TaskStatus.downloading.description() + downloadingArray.append(downloadModel) } else { downloadModel.status = TaskStatus.failed.description() } @@ -171,11 +174,14 @@ extension MZDownloadManager: URLSessionDownloadDelegate { public func urlSession(_ session: URLSession, downloadTask: URLSessionDownloadTask, didWriteData bytesWritten: Int64, totalBytesWritten: Int64, totalBytesExpectedToWrite: Int64) { for (index, downloadModel) in self.downloadingArray.enumerated() { if downloadTask.isEqual(downloadModel.task) { - DispatchQueue.main.async(execute: { () -> Void in + DispatchQueue.main.async(execute: {[weak self] () -> Void in + guard let self = self else { + return + } let taskStartedDate = downloadModel.startTime ?? Date() let timeInterval = taskStartedDate.timeIntervalSinceNow let downloadTime = TimeInterval(-1 * timeInterval) - + let receivedBytesCount = Double(downloadTask.countOfBytesReceived) let totalBytesCount = Double(downloadTask.countOfBytesExpectedToReceive) @@ -232,13 +238,12 @@ extension MZDownloadManager: URLSessionDownloadDelegate { if fileManager.fileExists(atPath: basePath) { let fileURL = URL(fileURLWithPath: destinationPath as String) debugPrint("directory path = \(destinationPath)") - do { try fileManager.moveItem(at: location, to: fileURL) } catch let error as NSError { debugPrint("Error while moving downloaded file to destination path:\(error)") - DispatchQueue.main.async(execute: { () -> Void in - self.delegate?.downloadRequestDidFailedWithError?(error, downloadModel: downloadModel, index: index) + DispatchQueue.main.async(execute: {[weak self] () -> Void in + self?.delegate?.downloadRequestDidFailedWithError?(error, downloadModel: downloadModel, index: index) }) } } else { @@ -246,7 +251,6 @@ extension MZDownloadManager: URLSessionDownloadDelegate { //Move downloaded file to destination //Delegate will be called on the session queue //Otherwise blindly give error Destination folder does not exists - if let _ = self.delegate?.downloadRequestDestinationDoestNotExists { self.delegate?.downloadRequestDestinationDoestNotExists?(downloadModel, index: index, location: location) } else { @@ -264,8 +268,10 @@ extension MZDownloadManager: URLSessionDownloadDelegate { debugPrint("task id: \(task.taskIdentifier)") /***** Any interrupted tasks due to any reason will be populated in failed state after init *****/ - DispatchQueue.main.async { - + DispatchQueue.main.async {[weak self] in + guard let self = self else { + return + } let err = error as NSError? if (err?.userInfo[NSURLErrorBackgroundTaskCancelledReasonKey] as? NSNumber)?.intValue == NSURLErrorCancelledReasonUserForceQuitApplication || (err?.userInfo[NSURLErrorBackgroundTaskCancelledReasonKey] as? NSNumber)?.intValue == NSURLErrorCancelledReasonBackgroundUpdatesDisabled { @@ -420,7 +426,6 @@ extension MZDownloadManager { downloadModel.status = TaskStatus.downloading.description() downloadingArray[index] = downloadModel - delegate?.downloadRequestDidResumed?(downloadModel, index: index) } From f6ff4745e638bafb3ea1236f8d693221e08c8512 Mon Sep 17 00:00:00 2001 From: SunCJ Date: Thu, 29 Nov 2018 14:34:39 +0800 Subject: [PATCH 4/5] chore: swifty style --- .../Classes/MZDownloadManager.swift | 31 ++++++++++--------- 1 file changed, 17 insertions(+), 14 deletions(-) diff --git a/MZDownloadManager/Classes/MZDownloadManager.swift b/MZDownloadManager/Classes/MZDownloadManager.swift index c4f7da0..b7ae68e 100644 --- a/MZDownloadManager/Classes/MZDownloadManager.swift +++ b/MZDownloadManager/Classes/MZDownloadManager.swift @@ -146,26 +146,29 @@ extension MZDownloadManager { fileprivate func isValidResumeData(_ resumeData: Data?) -> Bool { - guard resumeData != nil || resumeData?.count > 0 else { + guard let resumeData = resumeData, resumeData.count > 0 else { return false } - do { - var resumeDictionary : AnyObject! - resumeDictionary = try PropertyListSerialization.propertyList(from: resumeData!, options: PropertyListSerialization.MutabilityOptions(), format: nil) as AnyObject - var localFilePath = (resumeDictionary?["NSURLSessionResumeInfoLocalPath"] as? String) - - if localFilePath == nil || localFilePath?.count < 1 { - localFilePath = (NSTemporaryDirectory() as String) + (resumeDictionary["NSURLSessionResumeInfoTempFileName"] as! String) + guard let resumeDictionary = try? PropertyListSerialization.propertyList(from: resumeData, options: PropertyListSerialization.MutabilityOptions(), format: nil) as AnyObject else { + return false + } + + var localFilePath: String? = resumeDictionary["NSURLSessionResumeInfoLocalPath"] as? String + + if (localFilePath?.isEmpty ?? true) { + guard let filename = resumeDictionary["NSURLSessionResumeInfoTempFileName"] as? String else { + return false } - - let fileManager : FileManager! = FileManager.default - debugPrint("resume data file exists: \(fileManager.fileExists(atPath: localFilePath! as String))") - return fileManager.fileExists(atPath: localFilePath! as String) - } catch let error as NSError { - debugPrint("resume data is nil: \(error)") + localFilePath = NSTemporaryDirectory() + filename + } + guard let tempfile = localFilePath else { return false } + let fileManager: FileManager = FileManager.default + debugPrint("resume data file exists: \(fileManager.fileExists(atPath: tempfile))") + + return fileManager.fileExists(atPath: tempfile) } } From 50cd486de36ac7bcbde2438d166b5fbb8bc8b7da Mon Sep 17 00:00:00 2001 From: SamsonCJ Date: Tue, 25 Feb 2020 18:13:40 +0800 Subject: [PATCH 5/5] fix: crash when speed == 0 --- MZDownloadManager/Classes/MZDownloadManager.swift | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/MZDownloadManager/Classes/MZDownloadManager.swift b/MZDownloadManager/Classes/MZDownloadManager.swift index b7ae68e..f03bbb0 100644 --- a/MZDownloadManager/Classes/MZDownloadManager.swift +++ b/MZDownloadManager/Classes/MZDownloadManager.swift @@ -193,11 +193,12 @@ extension MZDownloadManager: URLSessionDownloadDelegate { } let progress = Float(receivedBytesCount / totalBytesCount) - let speed = Float(totalBytesWritten) / Float(downloadTime) + let speedFloat = Float(totalBytesWritten) / Float(downloadTime) + let speed = max(1, Int64(speedFloat)) let remainingContentLength = totalBytesExpectedToWrite - totalBytesWritten - let remainingTime = remainingContentLength / Int64(speed) + let remainingTime = remainingContentLength / speed let hours = Int(remainingTime) / 3600 let minutes = (Int(remainingTime) - hours * 3600) / 60 let seconds = Int(remainingTime) - hours * 3600 - minutes * 60 @@ -208,8 +209,8 @@ extension MZDownloadManager: URLSessionDownloadDelegate { let downloadedFileSize = MZUtility.calculateFileSizeInUnit(totalBytesWritten) let downloadedSizeUnit = MZUtility.calculateUnit(totalBytesWritten) - let speedSize = MZUtility.calculateFileSizeInUnit(Int64(speed)) - let speedUnit = MZUtility.calculateUnit(Int64(speed)) + let speedSize = MZUtility.calculateFileSizeInUnit(speed) + let speedUnit = MZUtility.calculateUnit(speed) downloadModel.remainingTime = (hours, minutes, seconds) downloadModel.file = (totalFileSize, totalFileSizeUnit as String)