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
}
}