Last active
October 13, 2016 05:11
-
-
Save piercifani/6975feda8664e4d828b2581dda941847 to your computer and use it in GitHub Desktop.
Crash on observing NSProgress
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import UIKit | |
@UIApplicationMain | |
class AppDelegate: UIResponder, UIApplicationDelegate { | |
var window: UIWindow? | |
var observer: ProgressObserver? | |
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool { | |
let task = SyncAllInteractor.syncAll() | |
task.upon { | |
print($0) | |
} | |
observer = ProgressObserver(progress: task.progress, onUpdate: { (progress) in | |
print(progress.fractionCompleted) | |
}) | |
return true | |
} | |
} | |
// MARK:- Make Tasks Great Again | |
import Foundation | |
import Deferred | |
class SyncAllInteractor: NSObject { | |
typealias SyncHandler = (NSError?) -> Void | |
static func syncAll() -> Task<()> { | |
return syncFolder(folderID: "69") | |
} | |
static func sync(items: [Item]) -> [Task<()>] { | |
return items.map { (item) in | |
if item.isFolder { | |
return self.syncFolder(folder: item as! Folder) | |
} else { | |
return self.sync(file: item as! File) | |
} | |
} | |
} | |
static func syncFolder(folderID: String) -> Task<()> { | |
return fetchFolderInfo(folderID: folderID).andThen(upon: DispatchQueue.any()) { (items) in | |
return sync(items: items).allSucceeded() | |
} | |
} | |
static func syncFolder(folder: Folder) -> Task<()> { | |
return syncFolder(folderID: folder.modelID) | |
} | |
static func sync(file: File) -> Task<()> { | |
let deferred = Deferred<TaskResult<()>>() | |
DispatchQueue.global().async { | |
deferred.fill(with: .success(())) | |
} | |
let progress = Progress(totalUnitCount: 1) | |
progress.isPausable = false | |
progress.isCancellable = true | |
progress.cancellationHandler = { | |
//NO OP | |
print("Attempt to cancel") | |
} | |
return Task(future: Future(deferred), progress: progress) | |
} | |
static func fetchFolderInfo(folderID: String) -> Task<[Item]> { | |
let deferred = Deferred<TaskResult<[Item]>>() | |
DispatchQueue.global().async { | |
let items = [File(), File(), File(), File(), File()] | |
deferred.fill(with: .success((items))) | |
} | |
let progress = Progress(totalUnitCount: 1) | |
progress.isPausable = false | |
progress.isCancellable = true | |
progress.cancellationHandler = { | |
//NO OP | |
print("Attempt to cancel") | |
} | |
return Task(future: Future(deferred), progress: progress) | |
} | |
} | |
//MARK: Model | |
protocol Item { | |
var modelID: String { get } | |
var isFolder: Bool { get } | |
var isFile: Bool { get } | |
} | |
struct File: Item { | |
var modelID: String = String.random() | |
let isFolder: Bool = false | |
let isFile: Bool = true | |
} | |
struct Folder: Item { | |
var modelID: String = String.random() | |
let isFolder: Bool = true | |
let isFile: Bool = false | |
} | |
extension String { | |
static func random(length: Int = 20) -> String { | |
let base = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789" | |
var randomString: String = "" | |
for _ in 0..<length { | |
let randomValue = arc4random_uniform(UInt32(base.characters.count)) | |
randomString += "\(base[base.index(base.startIndex, offsetBy: Int(randomValue))])" | |
} | |
return randomString | |
} | |
} | |
//MARK: - ProgressObserver | |
public class ProgressObserver: NSObject { | |
fileprivate let onUpdate: (Progress) -> Void | |
fileprivate let progress: Progress | |
public init(progress: Progress, onUpdate: @escaping (Progress) -> Void) { | |
self.progress = progress | |
self.onUpdate = onUpdate | |
super.init() | |
progress.addObserver(self, forKeyPath: "fractionCompleted", options: .new, context: nil) | |
} | |
override public func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) { | |
if let progress = object as? Progress , progress == self.progress { | |
DispatchQueue.main.async { | |
self.onUpdate(progress) | |
} | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment