Proyectos de Subversion Iphone Microlearning

Rev

Autoría | Ultima modificación | Ver Log |

//
//  ImageLoader.swift
//  twogetskills
//
//  Created by Efrain Yanez Recanatini on 3/9/22.
//

import Combine
import UIKit


class ImageLoader: ObservableObject {
    @Published var image: UIImage?
    
    private(set) var isLoading = false
    
    private let url: URL
    private var cache: ImageCache?
    private var cancellable: AnyCancellable?
    
    private static let imageProcessingQueue = DispatchQueue(label: "image-processing")
    
    init(url: URL, cache: ImageCache? = nil) {
        self.url = url
        self.cache = cache
    }
    
    deinit {
        cancel()
    }
    
    func load() {
        guard !isLoading else { return }

        if let image = cache?[url] {
            self.image = image
            return
        }
        
        let preference = Preference.sharedInstance
        let headerSecurity = HeaderSecurity()
        


        var request = URLRequest(url: url)
        request.httpMethod = "GET"
        request.addValue(preference.deviceUuid, forHTTPHeaderField: Constants.HTTP_HEADER_SECURITY_TOKEN)
        request.addValue(headerSecurity.secret, forHTTPHeaderField: Constants.HTTP_HEADER_SECURITY_SECRET)
        request.addValue(String(headerSecurity.created), forHTTPHeaderField: Constants.HTTP_HEADER_SECURITY_CREATED)
        request.addValue(String(headerSecurity.rand), forHTTPHeaderField: "Content-Type")

        
        cancellable = URLSession.shared.dataTaskPublisher(for: request)
            .map { UIImage(data: $0.data) }
            .replaceError(with: nil)
            .handleEvents(receiveSubscription: { [weak self] _ in self?.onStart() },
                          receiveOutput: { [weak self] in self?.cache($0) },
                          receiveCompletion: { [weak self] _ in self?.onFinish() },
                          receiveCancel: { [weak self] in self?.onFinish() })
            .subscribe(on: Self.imageProcessingQueue)
            .receive(on: DispatchQueue.main)
            .sink { [weak self] in self?.image = $0 }
    }
    
    func cancel() {
        cancellable?.cancel()
    }
    
    private func onStart() {
        isLoading = true
    }
    
    private func onFinish() {
        isLoading = false
    }
    
    private func cache(_ image: UIImage?) {
        image.map { cache?[url] = $0 }
    }
    
}