Fix #112 (crash on progress report)
This commit is contained in:
@@ -525,7 +525,7 @@ open class HTTPFileProvider: NSObject, FileProviderBasicRemote, FileProviderOper
|
||||
self?.delegateNotify(operation, error: responseError ?? error)
|
||||
}
|
||||
task.taskDescription = operation.json
|
||||
task.addObserver(self.sessionDelegate!, forKeyPath: #keyPath(URLSessionTask.countOfBytesSent), options: .new, context: &progress)
|
||||
sessionDelegate?.observerProgress(of: task, using: progress, kind: .upload)
|
||||
progress.cancellationHandler = { [weak task] in
|
||||
task?.cancel()
|
||||
}
|
||||
@@ -627,8 +627,7 @@ open class HTTPFileProvider: NSObject, FileProviderBasicRemote, FileProviderOper
|
||||
}
|
||||
|
||||
task.taskDescription = operation.json
|
||||
task.addObserver(sessionDelegate!, forKeyPath: #keyPath(URLSessionTask.countOfBytesReceived), options: .new, context: &progress)
|
||||
task.addObserver(sessionDelegate!, forKeyPath: #keyPath(URLSessionTask.countOfBytesExpectedToReceive), options: .new, context: &progress)
|
||||
sessionDelegate?.observerProgress(of: task, using: progress, kind: .download)
|
||||
progress.cancellationHandler = { [weak task] in
|
||||
task?.cancel()
|
||||
}
|
||||
@@ -667,8 +666,7 @@ open class HTTPFileProvider: NSObject, FileProviderBasicRemote, FileProviderOper
|
||||
}
|
||||
|
||||
task.taskDescription = operation.json
|
||||
task.addObserver(sessionDelegate!, forKeyPath: #keyPath(URLSessionTask.countOfBytesReceived), options: .new, context: &progress)
|
||||
task.addObserver(sessionDelegate!, forKeyPath: #keyPath(URLSessionTask.countOfBytesExpectedToReceive), options: .new, context: &progress)
|
||||
sessionDelegate?.observerProgress(of: task, using: progress, kind: .download)
|
||||
progress.cancellationHandler = { [weak task] in
|
||||
task?.cancel()
|
||||
}
|
||||
@@ -708,8 +706,7 @@ open class HTTPFileProvider: NSObject, FileProviderBasicRemote, FileProviderOper
|
||||
completionHandler(tempURL, nil)
|
||||
}
|
||||
task.taskDescription = operation.json
|
||||
task.addObserver(sessionDelegate!, forKeyPath: #keyPath(URLSessionTask.countOfBytesReceived), options: .new, context: &progress)
|
||||
task.addObserver(sessionDelegate!, forKeyPath: #keyPath(URLSessionTask.countOfBytesExpectedToReceive), options: .new, context: &progress)
|
||||
sessionDelegate?.observerProgress(of: task, using: progress, kind: .download)
|
||||
progress.cancellationHandler = { [weak task] in
|
||||
task?.cancel()
|
||||
}
|
||||
|
||||
@@ -258,7 +258,7 @@ internal extension OneDriveFileProvider {
|
||||
dictionary["uploadedBytes"] = NSNumber(value: uploadedSoFar)
|
||||
dictionary["totalBytes"] = NSNumber(value: data.count)
|
||||
task.taskDescription = String(jsonDictionary: dictionary)
|
||||
task.addObserver(self.sessionDelegate!, forKeyPath: #keyPath(URLSessionTask.countOfBytesSent), options: .new, context: &progress)
|
||||
sessionDelegate?.observerProgress(of: task, using: progress, kind: .upload)
|
||||
progress.cancellationHandler = { [weak task, weak self] in
|
||||
task?.cancel()
|
||||
var deleteRequest = URLRequest(url: url)
|
||||
|
||||
+43
-34
@@ -61,10 +61,49 @@ final public class SessionDelegate: NSObject, URLSessionDataDelegate, URLSession
|
||||
self.credential = fileProvider.credential
|
||||
}
|
||||
|
||||
public enum ObserveKind {
|
||||
case upload
|
||||
case download
|
||||
}
|
||||
|
||||
private let observeProgressesLock = NSLock()
|
||||
private var observeProgresses = [(task: URLSessionTask, progress: Progress, kind: ObserveKind)]()
|
||||
|
||||
public func observerProgress(of task: URLSessionTask, using: Progress, kind: ObserveKind) {
|
||||
switch kind {
|
||||
case .upload:
|
||||
task.addObserver(self, forKeyPath: #keyPath(URLSessionTask.countOfBytesSent), options: .new, context: nil)
|
||||
case .download:
|
||||
task.addObserver(self, forKeyPath: #keyPath(URLSessionTask.countOfBytesReceived), options: .new, context: nil)
|
||||
task.addObserver(self, forKeyPath: #keyPath(URLSessionTask.countOfBytesExpectedToReceive), options: .new, context: nil)
|
||||
}
|
||||
observeProgressesLock.lock()
|
||||
observeProgresses.append((task, using, kind))
|
||||
observeProgressesLock.unlock()
|
||||
}
|
||||
|
||||
func removeObservers(for task: URLSessionTask) {
|
||||
observeProgressesLock.lock()
|
||||
observeProgresses = observeProgresses.filter { (item) -> Bool in
|
||||
if item.task == task {
|
||||
switch item.kind {
|
||||
case .upload:
|
||||
task.removeObserver(self, forKeyPath: #keyPath(URLSessionTask.countOfBytesSent))
|
||||
case .download:
|
||||
task.removeObserver(self, forKeyPath: #keyPath(URLSessionTask.countOfBytesReceived))
|
||||
task.removeObserver(self, forKeyPath: #keyPath(URLSessionTask.countOfBytesExpectedToReceive))
|
||||
}
|
||||
return false
|
||||
} else {
|
||||
return true
|
||||
}
|
||||
}
|
||||
observeProgressesLock.unlock()
|
||||
}
|
||||
|
||||
public override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
|
||||
guard let context = context, let keyPath = keyPath else { return }
|
||||
let progress = Unmanaged<Progress>.fromOpaque(context).takeRetainedValue()
|
||||
guard progress.responds(to: #selector(Progress.becomeCurrent(withPendingUnitCount:))) else { return }
|
||||
guard let context = context, let keyPath = keyPath, keyPath.contains("countOfBytes") else { return }
|
||||
let progress = context.assumingMemoryBound(to: Progress.self).pointee
|
||||
guard let newVal = change?[.newKey] as? Int64 else { return }
|
||||
|
||||
switch keyPath {
|
||||
@@ -108,13 +147,7 @@ final public class SessionDelegate: NSObject, URLSessionDataDelegate, URLSession
|
||||
|
||||
// codebeat:disable[ARITY]
|
||||
public func urlSession(_ session: URLSession, task: URLSessionTask, didCompleteWithError error: Error?) {
|
||||
if task is URLSessionUploadTask {
|
||||
task.removeObserver(self, forKeyPath: #keyPath(URLSessionTask.countOfBytesSent))
|
||||
//task.removeObserver(self, forKeyPath: #keyPath(URLSessionTask.countOfBytesExpectedToSend))
|
||||
} else if task is URLSessionDownloadTask {
|
||||
task.removeObserver(self, forKeyPath: #keyPath(URLSessionTask.countOfBytesReceived))
|
||||
task.removeObserver(self, forKeyPath: #keyPath(URLSessionTask.countOfBytesExpectedToReceive))
|
||||
}
|
||||
self.removeObservers(for: task)
|
||||
|
||||
_ = dataCompletionHandlersForTasks[session.sessionDescription!]?.removeValue(forKey: task.taskIdentifier)
|
||||
if !(error == nil && task is URLSessionDownloadTask) {
|
||||
@@ -122,30 +155,6 @@ final public class SessionDelegate: NSObject, URLSessionDataDelegate, URLSession
|
||||
completionHandler?(error)
|
||||
_ = completionHandlersForTasks[session.sessionDescription!]?.removeValue(forKey: task.taskIdentifier)
|
||||
}
|
||||
|
||||
guard let json = task.taskDescription?.deserializeJSON(),
|
||||
let op = FileOperationType(json: json) else {
|
||||
return
|
||||
}
|
||||
|
||||
switch op {
|
||||
case .fetch:
|
||||
if task is URLSessionDataTask {
|
||||
task.removeObserver(self, forKeyPath: #keyPath(URLSessionTask.countOfBytesReceived))
|
||||
task.removeObserver(self, forKeyPath: #keyPath(URLSessionTask.countOfBytesExpectedToReceive))
|
||||
}
|
||||
default:
|
||||
break
|
||||
}
|
||||
|
||||
if !(task is URLSessionDownloadTask), case FileOperationType.fetch = op {
|
||||
return
|
||||
}
|
||||
if #available(iOS 9.0, macOS 10.11, *) {
|
||||
if task is URLSessionStreamTask {
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public func urlSession(_ session: URLSession, downloadTask: URLSessionDownloadTask, didFinishDownloadingTo location: URL) {
|
||||
|
||||
Reference in New Issue
Block a user