Search code examples
jsonswiftuitableviewparsingtableview

How to properly remove func from ViewController swift


I'm quite tired because i feel there is simple solution but i can't find it for days! I'm trying to remove parseJSON() from ViewController so it looks better but it's not working when it's removed, yet it still parsing data. Inside ViewController this func works absolutely fine and showing tableView with parsed data. I tried to add reloadData() and it didn't help

https://i.sstatic.net/z5lgD.jpg - screenshots

class MainViewController: UIViewController {

private var companyModel: CompanyModel? 
private lazy var employeesTable: UITableView = { 
    let table = UITableView(frame: .zero, style: .grouped)
    table.register(UITableViewCell.self, forCellReuseIdentifier: "cell")
    return table
}()

override func viewDidLoad() {
    super.viewDidLoad()
    parseJSON()
    view.addSubview(employeesTable)
    employeesTable.frame = view.bounds
    employeesTable.delegate = self
    employeesTable.dataSource = self
}

private func parseJSON() {
    guard let url = URL(string: "https://run.mocky.io/v3/1d1cb4ec-73db-4762-8c4b-0b8aa3cecd4c") else { return }
    do {
        let jsonData = try Data(contentsOf: url)
        companyModel = try JSONDecoder().decode(CompanyModel.self, from: jsonData)
    } catch {
        print(error)
    }
}

It's working as you can see on second screenshot

import Foundation

class NetworkManager {
    
    var companyModel: CompanyModel?
    func parseJSON() {
        guard let url = URL(string: "https://run.mocky.io/v3/1d1cb4ec-73db-4762-8c4b-0b8aa3cecd4c") else { return }
        do {
            let jsonData = try Data(contentsOf: url)
            companyModel = try JSONDecoder().decode(CompanyModel.self, from: jsonData)
        } catch {
            print(error)
        }
    }
}

import UIKit

class MainViewController: UIViewController {
    
    var networkManager = NetworkManager()
    private var companyModel: CompanyModel?
    private lazy var employeesTable: UITableView = {
        let table = UITableView(frame: .zero, style: .grouped)
        table.register(UITableViewCell.self, forCellReuseIdentifier: "cell")
        return table
    }()

    override func viewDidLoad() {
        super.viewDidLoad()
        networkManager.parseJSON()
        view.addSubview(employeesTable)
        employeesTable.frame = view.bounds
        employeesTable.delegate = self
        employeesTable.dataSource = self
    }
}

but this one is not working, what am i doing wrong?


Solution

  • Your code has two critical problems

    First of all, I see you have two companyModel : first one in class NetworkManager and second in class MainViewController and both have no connection which each others. The reason table view shows data when you parse json in MainViewController because it connects to the companyModel in MainViewController. You must remove one of them.

    Second, when you parse json from URL, you should make an asynchronous function for parse Json in NetworkManager. Sometimes getting data from server may takes long time.

    Code will be like this

    class NetworkManager {
        func parseJSON(completion: @escaping(_ companyModel: CompanyModel?) -> Void) {
            guard let url = URL(string: "https://run.mocky.io/v3/1d1cb4ec-73db-4762-8c4b-0b8aa3cecd4c") else { return }
    
            do {
                let jsonData = try Data(contentsOf: url)
                let companyModel = try JSONDecoder().decode(CompanyModel.self, from: jsonData)
    
                // return data parse from server
                completion(companyModel)
            } catch {
                print(error)
            }
        }
    }
    
    class MainViewController: UIViewController {
        var networkManager = NetworkManager()
        private var companyModel: CompanyModel?
        private lazy var employeesTable: UITableView = {
            let table = UITableView(frame: .zero, style: .grouped)
            table.register(UITableViewCell.self, forCellReuseIdentifier: "cell")
            return table
        }()
    
        override func viewDidLoad() {
            super.viewDidLoad()
            view.addSubview(employeesTable)
            employeesTable.frame = view.bounds
            employeesTable.delegate = self
            employeesTable.dataSource = self
            
            // add this line
            self.initTableViewData()
        }
    
        func initTableViewData() {
            networkManager.parseJSON(completion: {
                companyModel in
                self.companyModel = companyModel
                self.employeesTable.reloadData()
            })
        }
    }