无法从Swift中的API获取图像

问题描述

我需要将每个口袋妖怪图像添加到我的CollectionView中,但无法弄清楚该怎么做。

我的结构如下:

struct Pokemon: Codable {
   var results: [Species]?
   var abilities: [Ability]?
   var height,weight: Int?
   var imageURL: String?
   var image: Data?
   var description: String?
   var evolutionChain: [EvolutionChain]?
   var id,attack,defense: Int?
   var name,type: String?
   var sprites: Sprites?
   var stats: [Stat]?

init(id: Int,dictionary: [String: AnyObject]) {
    
    self.id = id
    
    if let name = dictionary["name"] as? String {
        self.name = name
    }
    
    if let imageUrl = dictionary["imageUrl"] as? String {
        self.imageURL = imageUrl
    }
    
    if let description = dictionary["description"] as? String {
        self.description = description
    }
    
    if let weight = dictionary["weight"] as? Int {
        self.weight = weight
    }
    
    if let height = dictionary["height"] as? Int {
        self.height = height
    }
    
    if let defense = dictionary["defense"] as? Int {
        self.defense = defense
    }
    
    if let attack = dictionary["attack"] as? Int {
        self.attack = attack
    }
    
    if let type = dictionary["type"] as? String {
        self.type = type.capitalized
    }
  }
}

我的API调用如下:

func getOtherPokes(handler: @escaping ([Pokemon]) -> Void) {
    
    var pokemonArray = [Pokemon]()
    var myImage = UIImage()
    
    AF.request(secondAPI).responseJSON { (response) in

        do {

            guard let pokeFetched = response.value as? [AnyObject] else { return }
            
            print("You have \(pokeFetched.count) pokemon listed by now.")

            //  Get all the elements of the pokemon objects
            for (key,result) in pokeFetched.enumerated() {
                if let dictionary = result as? [String: AnyObject] {
                    var pokemon = Pokemon(id: key,dictionary: dictionary)
                    
                    guard let imageURL = pokemon.imageURL else { return }
                    
                    self.fetchImages(withUrl: imageURL) { (img) in
                        
                        var mysImage = pokemon.image
                        mysImage = img.pngData()
                        
                        print(mysImage)
                        
                        pokemonArray.append(pokemon)
                        
                        pokemonArray.sort { (poke1,poke2) -> Bool in
                            return poke1.id! < poke2.id!
                        }
                        
                        handler(pokemonArray)
                    }
                }
            }
        } catch {
            print("There was an error: \(error)")
        }
    }.resume()
}

PD:我不能将图像设置为UIImage类型,因为Pokemon结构符合Codable。

我不知道如何获取该图像并将其获取到我的CollectionViewcontroller。有帮助吗?

解决方法

我假设您的函数getOtherPokes正在运行,因此您可以在视图控制器上执行一系列口袋妖怪的操作,并在cellForItem函数上获取图像。

enum ServiceError: Error{
    case emptyData
    case connectionError
    case apiError
    
    var localizedDescription: String{
        switch self {
        case .apiError:
            return "Something went wrong."
        case .emptyData:
        return "Nothing was found,try again or change the filters."
        case .connectionError:
        return "Your phone is not connected,conecte it and try again."
        }
    }
}

//Your ImageTask Service
class ImageTask {
      
        private static let imageCache = NSCache<NSString,UIImage>()
        
        static func fetchImages(withUrl urlString: String,handler: @escaping (Result<UIImage,Error>) -> Void) {
           
           //  Get a url as a parameter,so I can use it on fetchPokes
           guard let url = URL(string: urlString) else { return }
           
            //Verify if the image is already on cache
            if let imageCached = ImageTask.imageCache.object(forKey: url.absoluteString as NSString){
                handler(.success(imageCached))
                return nil
            }
            
           AF.request(url).response { (response) in
               
            
            if let error = response.error {
                handler(.failure(ServiceError.apiError))
                print("There was an error downloading the image. Check it out: \n \(error)")
                return
            }
            
               guard let data = response.data,let image = UIImage(data: data) else {
                handler(.failure(ServiceError.emptyData))
                return
               }
               
               //Save image on cache
               ImageTask.imageCache.setObject(image,forKey: url.absoluteString as NSString)
               handler(.success(image))
               
           }.resume()
    
        }
        
        
    
        /// method to get image from cache
        static func getImageOnCache(by url: String) -> UIImage?{
            if let imageCached = ImageTask.imageCache.object(forKey: url as NSString){
                return imageCached
            }
            return nil
        }
        
        
        static func cleanCache(){
            ImageAPI.imageCache.removeAllObjects()
        }
        
    
    }
    
    
    class YourViewController: UIViewController,UICollectionViewDataSource{
        
        
        var pokemons: [Pokemon] = [Pokemon]()
        
        
        func collectionView(_ collectionView: UICollectionView,cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
            return confiCell(index: indexPath)
        }
        
        
        
        
        private func confiCell(index: IndexPath)->UICollectionViewCell{
            guard let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "YourIdentifier",for: index) as? YourCell else {
                return UICollectionViewCell()
            }
            
            if let url = pokemons[index.row].imageURL{
                
                //Verify if image already exist on cache
                if let imageDownloaded = ImageTask.getImageOnCache(by: url){
                    cell.populate(with: imageDownloaded)
                }else{
                    
                    ImageTask.fetchImages(withUrl: url){ result in
                        let image = try? result.get()
                        DispatchQueue.main.async {
                            if let img = image{
                                cell.populate(with: img)
                            }else{
                                // treat in case of error
                            }
                        }
                    }
                    
                }
                
            }
            
            return cell
        }
        
        
    }

相关问答

错误1:Request method ‘DELETE‘ not supported 错误还原:...
错误1:启动docker镜像时报错:Error response from daemon:...
错误1:private field ‘xxx‘ is never assigned 按Alt...
报错如下,通过源不能下载,最后警告pip需升级版本 Requirem...