71 lines
2.1 KiB
Swift
71 lines
2.1 KiB
Swift
import SwiftUI
|
||
import Combine
|
||
|
||
// 1. Класс для загрузки изображения с поддержкой кеширования
|
||
class ImageLoader: ObservableObject {
|
||
@Published var image: UIImage?
|
||
|
||
private var cancellable: AnyCancellable?
|
||
private let url: URL
|
||
private let cache = ImageCacheManager.shared
|
||
|
||
init(url: URL) {
|
||
self.url = url
|
||
}
|
||
|
||
deinit {
|
||
cancellable?.cancel()
|
||
}
|
||
|
||
func load() {
|
||
// Проверяем, есть ли изображение в кеше
|
||
if let cachedImage = cache.get(forKey: url.absoluteString) {
|
||
self.image = cachedImage
|
||
return
|
||
}
|
||
|
||
// Если в кеше нет, загружаем из сети
|
||
cancellable = URLSession.shared.dataTaskPublisher(for: url)
|
||
.map { UIImage(data: $0.data) }
|
||
.replaceError(with: nil)
|
||
.handleEvents(receiveOutput: { [weak self] image in
|
||
// Сохраняем загруженное изображение в кеш
|
||
if let image = image, let key = self?.url.absoluteString {
|
||
self?.cache.set(image, forKey: key)
|
||
}
|
||
})
|
||
.receive(on: DispatchQueue.main)
|
||
.assign(to: \.image, on: self)
|
||
}
|
||
|
||
func cancel() {
|
||
cancellable?.cancel()
|
||
}
|
||
}
|
||
|
||
// 2. View для отображения удаленного изображения
|
||
struct RemoteImageView: View {
|
||
@StateObject private var loader: ImageLoader
|
||
|
||
init(url: URL) {
|
||
_loader = StateObject(wrappedValue: ImageLoader(url: url))
|
||
}
|
||
|
||
var body: some View {
|
||
content
|
||
.onAppear(perform: loader.load)
|
||
.onDisappear(perform: loader.cancel)
|
||
}
|
||
|
||
private var content: some View {
|
||
Group {
|
||
if let image = loader.image {
|
||
Image(uiImage: image)
|
||
.resizable()
|
||
} else {
|
||
ProgressView() // Показываем индикатор загрузки
|
||
}
|
||
}
|
||
}
|
||
}
|