Created
April 8, 2016 17:35
-
-
Save brentsimmons/387c5ec75aa1a5373d929fd9f1ae5f43 to your computer and use it in GitHub Desktop.
Revisions
-
brentsimmons created this gist
Apr 8, 2016 .There are no files selected for viewing
This file contains hidden or 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 charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,139 @@ // This is the traditional version of the RxSwift-based gist posted here: // https://gist.github.com/cliss/51cb740b14f3cd56ba1d11f2a9a6ba02 // This won’t compile and it surely has errors. // (The same may be true as the original.) // Some things are obviously omitted. // It's meant as illustrative rather than as actual running code. // // The problem being solved: // There is a text field. When you type in it, all changes are coalesced // for 0.3 seconds, and then an HTTP call is made, and a table is updated // with results. // Also: there's a Refresh button, and tapping the Refresh button // runs that same HTTP call and updates the table with results. // Whenever there's an existing HTTP call, and a new one has been triggered, // the existing HTTP call should be canceled. struct Result { let text: String let someOtherThing: String } typealias FetcherCallback = (result: Result?, error: NSError?) -> Void class Fetcher { let task: NSURLSessionDataTask init(query: String, callback: FetcherCallback) { //Assume the url was created based on the query. And that myURLSession came from somewhere. self.task = myURLSession.dataTaskWithURL(url) { data, response, error in { if let error = error { callback(nil, error) return } let results: [Result] = something //make results from the data; obvious omission for the sake of argument callback(results, nil) } } self.task.resume() } func cancel() { task.cancel() } } class ViewController: UIViewController, UITableViewDataSource, UITableViewDelegate { private weak var tableView: UITableView! private weak var textField: UITextField! private var fetchTimer: NSTimer? private var fetcher: Fetcher? private var results = [String]() { didSet { tableView.reloadData() } } private var currentText = "" { didSet { if currentText.count < 4 { invalidateFetchTimer() } else { resetFetchTimer() } } } deinit { invalidateFetchTimer() cancelExistingFetch() } override func viewDidLoad() { textField.delegate = self } func textDidChange(sender: AnyObject) { if currentText != textField.stringValue { currentText = textField.stringValue } } private func invalidateFetchTimer() { if let timer = fetchTimer where fetchTimer.isValid { timer.invalidate() } fetchTimer = nil } private func resetFetchTimer() { invalidateFetchTimer() fetchTimer = NSTimer(timeInterval: 0.3, target: self, selector: #selector(fetchTimerDidFire(_:)), userInfo: nil, repeats: false) } dynamic func fetchTimerDidFire(sender: AnyObject) { runFetch() } private func cancelExistingFetch() { if let existingFetcher = fetcher { existingFetcher.cancel() } fetcher = nil } private func runFetch() { invalidateFetchTimer() cancelExistingFetch() fetcher = Fetcher(text: currentText) { result, error in if let error = error { //Handle it. } else { self.results = result.map { oneResult in return oneResult.text } } } } @IBAction func refresh(sender: AnyObject) { runFetch() } }