74 lines
		
	
	
		
			2.1 KiB
		
	
	
	
		
			Swift
		
	
	
	
	
	
			
		
		
	
	
			74 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 {
 | 
						||
                ZStack {
 | 
						||
                    Color(.systemGray5)
 | 
						||
                    ProgressView()
 | 
						||
                }
 | 
						||
            }
 | 
						||
        }
 | 
						||
    }
 | 
						||
}
 |