Skip to content

Instantly share code, notes, and snippets.

@KevinVitale
Last active April 1, 2016 14:10
Show Gist options
  • Save KevinVitale/1ec2b8ff79fdbdfb56d682555f18e67b to your computer and use it in GitHub Desktop.
Save KevinVitale/1ec2b8ff79fdbdfb56d682555f18e67b to your computer and use it in GitHub Desktop.
`PropertyType` for easily fetching images in ReactiveCocoa 4.0.1
import ReactiveCocoa
#if os(iOS)
public typealias ImageType = UIImage
#else
#if os(OSX)
public typealias ImageType = NSImage
#endif
#endif
// MARK: -
// MARK: Image Cacher Protocol
// MARK: -
public protocol ImageCacher {
func cachedImage(forURL url: String) -> ImageType?
func cache(image: ImageType, atURL url: String)
}
// MARK: -
// MARK: Image Resource
// MARK: -
public struct ImageProperty {
public typealias Value = ImageType?
// MARK: Properties (Private)
private let _buffer = SignalProducer<ImageType?, NSError>.buffer(1)
private let _image: MutableProperty<ImageType?> = MutableProperty(nil)
private var _fetch: Action<String, ImageType?, NSError>! = Action { _ in SignalProducer.empty }
// MARK: Initialization
public init(_ imageURL: String, imageCacher: ImageCacher? = nil) {
_fetch = Action { urlString in
SignalProducer { _ in
guard let url = NSURL(string: urlString) else {
self._buffer.1.sendNext(nil)
self._buffer.1.sendCompleted()
return
}
let request = NSURLRequest(URL: url)
let session = NSURLSession.sharedSession()
self._buffer.1.sendNext(imageCacher?.cachedImage(forURL: imageURL))
session
.rac_dataWithRequest(request)
.map { ImageType(data: $0.0) }
.takeWhile { $0 != nil }
.on(next: {
if let image = $0 {
imageCacher?.cache(image, atURL: imageURL)
}
})
.start(self._buffer.1)
}
}
_image <~ _buffer.0
.flatMapError { _ in SignalProducer<ImageType?, NoError>.empty }
_fetch.apply(imageURL).start()
}
}
// MARK: -
// MARK: Extension, Public Properties
// MARK: -
extension ImageProperty: PropertyType {
public var value: Value {
return _image.value
}
public var signal: Signal<Value, NoError> {
return _image.signal
}
public var producer: SignalProducer<Value, NoError> {
return _image.producer
}
public var isFetching: AnyProperty<Bool> {
return _fetch.executing
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment