-
-
Notifications
You must be signed in to change notification settings - Fork 637
/
ImageLoader.swift
63 lines (51 loc) · 1.75 KB
/
ImageLoader.swift
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
//
// ImageData.swift
// MovieSwift
//
// Created by Thomas Ricouard on 09/06/2019.
// Copyright © 2019 Thomas Ricouard. All rights reserved.
//
import SwiftUI
import UIKit
import Combine
class ImageLoaderCache {
static let shared = ImageLoaderCache()
var loaders: NSCache<NSString, ImageLoader> = NSCache()
func loaderFor(path: String?, size: ImageService.Size) -> ImageLoader {
let key = NSString(string: "\(path ?? "missing")#\(size.rawValue)")
if let loader = loaders.object(forKey: key) {
return loader
} else {
let loader = ImageLoader(path: path, size: size)
loaders.setObject(loader, forKey: key)
return loader
}
}
}
final class ImageLoader: ObservableObject {
let path: String?
let size: ImageService.Size
var objectWillChange: AnyPublisher<UIImage?, Never> = Publishers.Sequence<[UIImage?], Never>(sequence: []).eraseToAnyPublisher()
@Published var image: UIImage? = nil
var cancellable: AnyCancellable?
init(path: String?, size: ImageService.Size) {
self.size = size
self.path = path
self.objectWillChange = $image.handleEvents(receiveSubscription: { [weak self] sub in
self?.loadImage()
}, receiveCancel: { [weak self] in
self?.cancellable?.cancel()
}).eraseToAnyPublisher()
}
private func loadImage() {
guard let poster = path, image == nil else {
return
}
cancellable = ImageService.shared.fetchImage(poster: poster, size: size)
.receive(on: DispatchQueue.main)
.assign(to: \ImageLoader.image, on: self)
}
deinit {
cancellable?.cancel()
}
}