簡體   English   中英

Swift - 返回通用類型/數據

[英]Swift - Return Generic Type/Data

我有獲取數據的 URLSession 共享實例。 它返回一個泛型類型。 當我從服務器獲取數據並顯示它時,一切正常。 但是當我獲取圖像時,我需要將通用類型作為數據返回。 如何返回通用類型/數據,以便它可以用於在 imageView 中創建圖像?

UIImageView:

extension UIImageView {
    
    func loadImage(with url: URL) {
        
        if let cachedImage = imageCache.object(forKey: url.absoluteString as AnyObject) as? UIImage {
            self.image = cachedImage
            return
        }
        
        URLSessionManager.fetchData(with: url, isImageFetch: true) { (result: Result<Data, SessionDataTaskError>) in

            switch result {

            case .failure(let error):

                print(error)

            case .success(let data):

                guard let downloadedImage = UIImage(data: data) else {
                    print("image data is nil")
                    return
                }

                DispatchQueue.main.async{ [weak self] in

                    imageCache.setObject(downloadedImage, forKey: url.absoluteString as AnyObject)
                    self?.image = downloadedImage
                }
            }
        }
    }
}

URL會話管理器:

class URLSessionManager {
    
    static let shared = URLSessionManager()
    
    static func fetchData<T: Decodable>(with url: URL, isImageFetch: Bool = false, completion: @escaping (Result<T, SessionDataTaskError>)->Void) { // SessionDataTaskError is just an Enum
        
        URLSession.shared.dataTask(with: url) { (data, response, error) in
            
            if let error = error {
                completion(.failure(SessionDataTaskError.failedIssue(error)))
                return
            }
            
            guard let data = data else {
                completion(.failure(SessionDataTaskError.dataIsNil))
                return
            }
            
            if isImageFetch {

                // *** How can I return the generic type/data so that it can be used to create the image in the imageView? ***
                return
            }

            do {
                
                let genericType = try JSONDecoder().decode(T.self, from: data)
                
                completion(.success(genericType))
                
            } catch {
                
                completion(.failure(SessionDataTaskError.catchIssue(error)))
                
                guard let err = error as? DecodingError else {
                    debugPrint("decodingError-:", error)
                    return
                }
                
                switch err {
                case .typeMismatch(let key, let value):
                    print("decodingError-Mismatch: \(key), value \(value) and ERROR: \(error.localizedDescription)")
                case .valueNotFound(let key, let value):
                    print("decodingError-ValueNotFound: \(key), value \(value) and ERROR: \(error.localizedDescription)")
                case .keyNotFound(let key, let value):
                    print("decodingError-KeyNotFound(: \(key), value \(value) and ERROR: \(error.localizedDescription)")
                case .dataCorrupted(let key):
                    print("decodingError-DataCorrupted: \(key), and ERROR: \(error.localizedDescription)")
                default:
                    print("decodingError-UnknownError: \(error.localizedDescription)")
                }
            }
            
        }.resume()
    }
}

fetchData<T: Decodable>用於在響應主體上執行JSONDecoder 但是圖像不是 JSON,因此當響應實際上是圖像時調用該方法沒有意義。 通常,您將有一個單獨的實現來返回DataUIImage

所以我會有一個非通用的fetchData ,它在成功時檢索Data 然后我會有一個通用的fetchObject調用fetchData JSONDecoder泛型。 我會有一個非通用的fetchImage ,它也調用fetchData ,但它返回一個UIImage


順便說一句,我會非常小心loadImage(with:) 您不只是想更新UIImageView ,因為存在風險(尤其是對於集合和表格視圖)單元格可能會在中間時間被重用,這可能會導致非常奇怪的結果,如果您正在滾動可能會出現錯誤的圖像快速通過集合/表格視圖)。 請參閱https://stackoverflow.com/a/45183939/1271826以了解使用“關聯對象”來跟蹤未決請求(如果有)的示例。 如果用戶快速滾動,這種模式還可以避免它積壓。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM