I’m trying to fetch data from an API
I want the data to be displayed in the tableview
If I give items some static values, it works but the async operation does not work.
what i am doing wrong here?
please point out my mistake.
thank you!
Model:
struct User: Codable {
let id: Int
let name, username, email: String
let address: Address
let phone, website: String?
let company: Company?
}
struct Address: Codable {
let street, suite, city, zipcode: String
let geo: Geo
}
struct Geo: Codable {
let lat, lng: String
}
struct Company: Codable {
let name, catchPhrase, bs: String
}
struct Item {
let name: String
}
ViewModel
class ItemViewModel: ObservableObject {
@Published var items: [Item] = []
private let apiUrl = "https://jsonplaceholder.typicode.com/users"
func fetchData() {
guard let url = URL(string: apiUrl) else {
print("Invalid URL")
return
}
URLSession.shared.dataTask(with: url) { data, response, error in
guard let data = data, error == nil else {
print("Error: (error?.localizedDescription ?? "Unknown error")")
return
}
do {
let users = try JSONDecoder().decode([User].self, from: data)
DispatchQueue.main.async {
self.items = users.map { Item(name: $0.name) }
}
} catch {
print("Error decoding JSON: (error.localizedDescription)")
}
}.resume()
}
}
Controller
class ViewController: UIViewController {
let cellID = "cellID"
let viewModel = ItemViewModel()
let tableView: UITableView = {
let tableView = UITableView()
tableView.backgroundColor = .red
return tableView
}()
override func viewDidLoad() {
super.viewDidLoad()
tableView.register(UITableViewCell.self, forCellReuseIdentifier: cellID)
setUpView()
viewModel.fetchData()
}
private func setUpView() {
view.addSubview(tableView)
tableView.dataSource = self
tableView.delegate = self
tableView.translatesAutoresizingMaskIntoConstraints = false
tableView.topAnchor.constraint(equalTo: view.topAnchor).isActive = true
tableView.leftAnchor.constraint(equalTo: view.leftAnchor).isActive = true
tableView.bottomAnchor.constraint(equalTo: view.bottomAnchor).isActive = true
tableView.rightAnchor.constraint(equalTo: view.rightAnchor).isActive = true
}
}
extension ViewController: UITableViewDataSource, UITableViewDelegate {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return viewModel.items.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: cellID, for: indexPath)
cell.textLabel?.text = viewModel.items[indexPath.row].name
return cell
}
}
Nothing is displayed if i make API call, If i make a static array this works.
What is it that i am missing here?