Skip to content

Instantly share code, notes, and snippets.

@azonov
Last active March 30, 2023 17:25
Show Gist options
  • Save azonov/1dcb695e004b74835eb322ab5977e1c7 to your computer and use it in GitHub Desktop.
Save azonov/1dcb695e004b74835eb322ab5977e1c7 to your computer and use it in GitHub Desktop.
//
// ViewController.swift
// Demo
//
// Created by Andey on 04.01.2023.
//
import Combine
import UIKit
protocol IGenerator {
func randomImagePublisher() -> AnyPublisher<UIImage, Error>
}
class ViewController: UIViewController {
enum State {
case loading
case image(UIImage)
}
@IBOutlet private weak var button: UIButton!
@IBOutlet private weak var imageView: UIImageView!
@IBOutlet private weak var activityIndicator: UIActivityIndicatorView!
private var generator: IGenerator = Generator()
private var imageRequest: Cancellable?
private var state: State = .loading {
didSet {
switch state {
case .image(let image):
self.imageView.image = image
self.activityIndicator.stopAnimating()
case .loading:
self.activityIndicator.startAnimating()
}
}
}
@IBAction func onTap(sender: UIButton) {
loadImage1()
loadImage2()
}
func loadImage1() {
state = .loading
imageRequest = generator
.randomImagePublisher()
.retry(1)
.tryMap(UIImage.applyBloomFilter)
.subscribe(on: DispatchQueue.global(qos: .utility))
.receive(on: DispatchQueue.main)
.catch({ _ in Just(UIImage.placeholderImage) })
.handleEvents(receiveCancel: { print("Cancel") })
.map(State.image)
.assign(to: \.state, onWeak: self)// on->onWeak
}
func loadImage2() {
state = .loading
imageRequest = generator
.randomImagePublisher()
.retry(1)
.tryMap(UIImage.applyBloomFilter)
.subscribe(on: DispatchQueue.global(qos: .utility))
.receive(on: DispatchQueue.main)
.catch({ _ in Just(UIImage.placeholderImage) })
.handleEvents(receiveCancel: { print("Cancel") })
.map(State.image)
.assign(to: \.unwrap.state, on: weak(link)) // weak
}
}
// For loadImage1
extension Publisher where Failure == Never {
func assign<Root: AnyObject>(
to keyPath: ReferenceWritableKeyPath<Root, Output>,
onWeak object: Root
) -> AnyCancellable {
sink { [weak object] value in
object?[keyPath: keyPath] = value//KVO
}
}
}
// For loadImage2
struct Weakify<Object: AnyObject> {
weak var object: Object?
var unwrap: Object {
object!
}
}
func weak<Object: AnyObject>(_ object: Object) -> Weakify<Object> {
Weakify(object: object)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment