Home > Enterprise >  No Display image in CollectionView
No Display image in CollectionView

Time:10-31

I've run into a problem that I can't handle. Now I am developing an application that displays photos. I am using api from unplash. Below I will show you my code.

My code is from ViewModel where I am making a request to the server:


class PhotoViewModel {
    //        let url = URL(string: "https://api.unsplash.com/photos/random/?count=30&client_id=\(key)")
    private let key = "KEY"
    private let authorization = "Authorization"
    var cell = HomeCollectionViewCell()
    var photo: [Photo] = []
    
    // MARK: func fetchPhoto
    func fetchPhoto(){
        let url = URL(string: "https://api.unsplash.com/photos")
        var request = URLRequest(url: url!)
        request.httpMethod = "GET"
        request.setValue("Client-ID KEY)", forHTTPHeaderField: "Authorization")
        
        URLSession.shared.dataTask(with: request) { data, response, error in
            if let data = data {
                do {
                    let image = try JSONDecoder().decode([Photo].self, from: data)
                    self.photo.append(contentsOf: image)
                    
                    print(image)
                    
                } catch let error {
                    print(error.localizedDescription)
                }
            }
        }.resume()
    }
    
    
}

This is my model that I am using

struct Photo: Codable {
    let id: String
    let created_at: String
    let width: Int
    let height: Int
    let likes: Int
    let urls: URLs
}
struct URLs: Codable {
    let raw: String
}

My cell where the data is displayed. To upload photos, I decided to use Kingfisher.

class HomeCollectionViewCell: UICollectionViewCell {

    @IBOutlet weak var unsplashPhoto: UIImageView!
    @IBOutlet weak var test: UILabel!
    
    func setup(photo: Photo) {
        let url = URL(string: photo.urls.raw)
        unsplashPhoto.kf.setImage(with: url)
        self.test.text = photo.created_at
    }
    
    
}

This is my main ViewController code.

class ViewController: UIViewController {
    var photos =  [Photo]()
    private var photoViewModel = PhotoViewModel()
    
    @IBOutlet weak var homeCV: UICollectionView!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        self.homeCV.dataSource = self
        self.homeCV.delegate = self
  
        photoViewModel.fetchPhoto()
        DispatchQueue.main.async {
            self.homeCV.reloadData()}

    }
    
}
extension ViewController:  UICollectionViewDataSource, UICollectionViewDelegate {
    
    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        return photos.count
    }
    
    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath) as! HomeCollectionViewCell
        let photo = photos[indexPath.row]
        cell.setup(photo: photo)
        return cell
        
    }
    
    
    
}

Tried different options. I can see my JSON file is showing up in the console, but the data is not showing up on the screen when I run the simulator.

CodePudding user response:

You are not having your data displayed because you are not populating your array from your ViewController. I would try to pass a completion handler with the data to the ViewController and populate there the dataSource. Your request is made but you are not passing the data further to the ViewController. I would rewrite the request from the viewModel like this:

func fetchPhoto(completion: @escaping (Result<[Photo], Error>) -> Void){
                   let url = URL(string: "https://api.unsplash.com/photos")
                   var request = URLRequest(url: url!)
                   request.httpMethod = "GET"
                   request.setValue("Client-ID KEY)", forHTTPHeaderField: "Authorization")
                   
                   URLSession.shared.dataTask(with: request) { data, response, error in
                       if let data = data {
                           do {
                               let image = try JSONDecoder().decode([Photo].self, from: data)
                               self.photo.append(contentsOf: image)
                               completion(.success(photo))
                               print(image)
                               
                           } catch let error {
                               completion(.failure(error))
                               print(error.localizedDescription)
                           }
                       }
                   }.resume()
               }

And in the ViewContrller call the request like this: And only call reloadData on the collectionView when the dataSource has been populated.

 photoViewModel.fetchPhoto { result in
            switch result {
            case .success(let data):
                self.photos = data
                DispatchQueue.main.async { [weak self] in
                    self?.homeCV.reloadData()
                }
            case .failure(let err):
                break
            }
       }
  • Related