Created
April 8, 2016 17:35
-
-
Save brentsimmons/387c5ec75aa1a5373d929fd9f1ae5f43 to your computer and use it in GitHub Desktop.
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
// 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() | |
} | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment