Skip to content

Instantly share code, notes, and snippets.

@jarsen
Created June 29, 2015 17:15
Show Gist options
  • Save jarsen/7d4c8e40a728d3920b18 to your computer and use it in GitHub Desktop.
Save jarsen/7d4c8e40a728d3920b18 to your computer and use it in GitHub Desktop.
// .-'
// '--./ / _.---.
// '-, (__..-` \
// \ . |
// `,.__. ,__.--/
// '._/_.'___.-`
import Foundation
import ReactiveCocoa
import Orcinus
import RealmSwift
/// Uses download signal to fetch objects from API endpoint
/// and adds them to the realm. It sends a notification through
/// its update signal every time new items are downloaded so
/// observers know to refresh their realm query
public class Fetcher<T: Object> {
/// Give the fetcher a name so it can be identified
public let name: String?
/// Subscribe to this signal to be notified of updates.
/// The signal will always send `true`. It is just so
/// you know when you might refresh relevant realm queries.
public let updateSignal: Signal<Bool, NoError>
private let downloadSignal: Signal<T, Error>
private let sink: SinkOf<Event<Bool, NoError>>
private let namePrefix: String
public var debug = false
public init(name: String?=nil, downloadSignal: Signal<T, Error>) {
self.name = name
self.namePrefix = name.map { "\($0) - " } ?? "" // either "MyFetcherName - " or ""
(updateSignal, sink) = Signal<Bool, NoError>.pipe()
self.downloadSignal = downloadSignal
self.downloadSignal.observe(error: handleError, completed: handleCompleted, interrupted: handleInterrupted, next: handleNext)
}
private func handleError(error: Error) {
if debug {
("\(namePrefix)Fetching error: \(error.nsError.localizedDescription)")
}
}
private func handleCompleted() {
if debug {
print("\(namePrefix)Completed.")
}
sendCompleted(sink)
}
private func handleInterrupted() {
if debug {
print("\(namePrefix)Fetching interrupted")
}
}
/// Adds the object to the realm and forwards the value down
/// through the publically exposed signal
private func handleNext(value: T) {
if debug {
print("\(namePrefix)Fetched: \(value)")
}
let realm = Realm()
realm.write {
realm.add(value, update: true)
}
sendNext(self.sink, true)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment