Skip to content

Instantly share code, notes, and snippets.

@odrobnik
Last active January 4, 2018 17:37
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save odrobnik/a02ac1e49ff90ec4f8a7 to your computer and use it in GitHub Desktop.
Save odrobnik/a02ac1e49ff90ec4f8a7 to your computer and use it in GitHub Desktop.
Upload progress reporting NSProgress for NSURLSessionTask
import Foundation
public class UploadProgress: NSProgress
{
var sessionTask: NSURLSessionTask!
required public init(sessionTask: NSURLSessionTask)
{
super.init(parent: nil, userInfo: nil)
self.sessionTask = sessionTask
self.cancellationHandler = { [weak self] in
self?.sessionTask?.cancel()
}
addObserver()
updateValues()
}
deinit
{
removeObserver()
}
func addObserver()
{
sessionTask.addObserver(self, forKeyPath: "countOfBytesExpectedToSend", options: NSKeyValueObservingOptions.New, context: nil)
sessionTask.addObserver(self, forKeyPath: "countOfBytesSent", options: NSKeyValueObservingOptions.New, context: nil)
sessionTask.addObserver(self, forKeyPath: "state", options: NSKeyValueObservingOptions.New, context: nil)
}
func removeObserver()
{
if sessionTask != nil
{
sessionTask.removeObserver(self, forKeyPath: "countOfBytesExpectedToSend", context: nil)
sessionTask.removeObserver(self, forKeyPath: "countOfBytesSent", context: nil)
sessionTask.removeObserver(self, forKeyPath: "state", context: nil)
// we can also give up the strong reference
sessionTask = nil
}
}
func updateValues()
{
self.totalUnitCount = sessionTask.countOfBytesExpectedToSend
self.completedUnitCount = sessionTask.countOfBytesSent
}
override public func observeValueForKeyPath(keyPath: String?, ofObject object: AnyObject?, change: [String : AnyObject]?, context: UnsafeMutablePointer<Void>)
{
if keyPath == "state"
{
if sessionTask.state == .Canceling || sessionTask.state == .Completed
{
// we are don with the observing
removeObserver()
}
}
else
{
updateValues()
}
}
}
import ObjectiveC
// Declare a global var to produce a unique address as the assoc object handle
var UploadProgressAssociatedObjectHandle: UInt8 = 0
public extension NSURLSessionTask
{
var uploadProgress: UploadProgress
{
get
{
if let existingProgress = objc_getAssociatedObject(self, &UploadProgressAssociatedObjectHandle) as? UploadProgress
{
return existingProgress
}
let progress = UploadProgress(sessionTask: self)
self.uploadProgress = progress
return progress
}
set
{
objc_setAssociatedObject(self, &UploadProgressAssociatedObjectHandle, newValue, objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN_NONATOMIC)
}
}
}
usage: let progress = dataTask.uploadProgress and observe fractionPercentage
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment