Home > other >  Network call is successful but the data not showing (swift)
Network call is successful but the data not showing (swift)

Time:12-21

I am trying to make a very simple app in MVVM and I must be missing something here but I can't figure it out. I have all the error handling in my NewsService class and I print success if all goes right and it receives the data. I get that success every time, the issue is the "print(articles)" are not printing anything at all.

class NewsTableViewModel {
    
    var articles = [Article]() {
        didSet {
            print(articles)
        }
    }
    
    func fetchNews() {

        NewsService.shared.fetchNews { [weak self] articles in
            guard let self = self else { return }
            self.articles = articles
            print(articles)
        }
    }
}
class NewsTableVC: UITableViewController, NewsTableViewModelDelegate {
    
    private let reuseIdentifier = "ArticleCell"
    private let newsTableVM = NewsTableViewModel()
    //    var article = [Article]() {
    //        didSet {
    //            DispatchQueue.main.async {
    //                self.tableView.reloadData()
    //            }
    //        }
    //    }
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        newsTableVM.delegate = self
        newsTableVM.fetchNews()
        updateUI()
    }
    
    func updateUI() {
        tableView.register(ArticleCell.self, forCellReuseIdentifier: reuseIdentifier)
        DispatchQueue.main.async {
            self.tableView.reloadData()
        }
    }
    
    override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        //        return article.count
        return self.newsTableVM.articles.count
    }

    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: reuseIdentifier, for: indexPath) as! ArticleCell
        //        cell.articleTitleLabel.text = article[indexPath.row].title
        //        cell.articleDescriptionLabel.text = article[indexPath.row].description
        cell.articleTitleLabel.text = newsTableVM.articles[indexPath.row].title
        cell.articleDescriptionLabel.text = newsTableVM.articles[indexPath.row].description
        return cell
    }

}
struct Response: Codable {
    
    let articles: [Article]
}

struct Article: Codable {
    
    let title: String
    let description: String
}
class NewsService {
    
    static let shared = NewsService()
    
    func fetchNews(completion: @escaping ([Article]) -> (Void)) {
        
        if let urlString = URL(string: "") {
            
            let task = URLSession.shared.dataTask(with: urlString) { data, response, error in
                if let _ = error {
                    print("error")
                    return
                }
                
                guard let response = response as? HTTPURLResponse, response.statusCode == 200 else { return }
                
                guard let data = data else {
                    return
                }
                
                let decoder = JSONDecoder()
                do {
                    print("success")
                    let articles = try decoder.decode(Response.self, from: data).articles
                    completion(articles)
                } catch {
                    return
                }
            }
            task.resume()
        }
    }
}

In my view controller viewDidLoad, I call NewsTableViewModel().fetchNews(). And here is the entire NewsTableViewModel class. Ignore the double use of print(articles), I'm just trying to figure out where it's going wrong.

CodePudding user response:

you did not cover all the cases, put debug print at:

guard let self = self else { 
    print("self is nill")
    return completion([])
}

and:

            guard let response = response as? HTTPURLResponse, response.statusCode == 200 else { 
                print("error: \(response)")
                return completion([])
            }
            
            guard let data = data else {
                print("error: data is nill")
                return completion([])
            }

and:

            do {
                print("success")
                let articles = try decoder.decode(Response.self, from: data).articles
                completion(articles)
            } catch (let error){
                print("catch an error: \(error)
                completion([])
            }

also put the completion([]) in the error cases instead of return only.

  • Related