user0246
user0246

Reputation: 65

table view datasource and delegate methods calling without loading data from web service?

In my application I had make call Json function and table view delegate and datasource methods in view did load but here without loading data from web service it is calling table view methods and inside it is crashing due to having no data from model can anyone help me how to resolve this and this is happening sometimes and sometimes it working properly ?

here is my view did load

let guestAddressURL = "http://magento.selldesk.io/index.php/rest/V1/guest-carts/\(guestkey!)/billing-address"
self.guestShippingaddressURL(guestAddressApi: guestAddressURL)
self.tableDetails.delegate = self
self.tableDetails.dataSource = self
self.tableDetails.tableFooterView?.isHidden = true
self.tableDetails.separatorInset = UIEdgeInsets.zero
self.tableDetails.rowHeight = UITableViewAutomaticDimension
self.tableDetails.estimatedRowHeight = 50
self.title = "Checkout"

here is my Json function

 func guestShippingaddressURL(guestAddressApi: String) {
        print(guestAddressApi)
        let url = URL(string: guestAddressApi)
        var request = URLRequest(url: url! as URL)
        request.httpMethod = "GET"
        request.addValue("application/json", forHTTPHeaderField: "Content-Type")
        let task = URLSession.shared.dataTask(with: request) { (data, response, error) in
            if error != nil { print(error!); return }
            do {
                if let jsonObj = try JSONSerialization.jsonObject(with: data!) as? [String:Any] {
                    let obj = jsonObj["street"] as! [String]
                    for item in obj  {
                        self.street = item
                    }
                    print(obj)
                    print(self.street)
                    self.guestShippingAddressModel = GuestAddress.init(dict: jsonObj)
                    if self.street?.isEmpty == false  {
                        self.addressSelected = true
                        self.selected = false
                    }
                    DispatchQueue.main.async {
                        self.tableDetails.reloadData()
                    }
                }
            } catch {
                print(error)
            }
        }
        task.resume()
    }
func numberOfSections(in tableView: UITableView) -> Int {
        if self.street?.isEmpty == false{
            return 3
        }
        else {
            if ((addressSelected == true || checkIsPaymentRadioSelect == true) && selected == false) {
                return 3
            }else {
                return 2
            }
        }
    }
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int{
        if ((addressSelected == true || checkIsPaymentRadioSelect == true) && selected == false) {
            if (section == 0)
            {

                return 1
            }
            else if (section == 1)
            {
                return 1
            }
            else
            {
                return 1
            }
        }
        else
        {
            if (section == 0)
            {
                return 1
            }
            else
            {
                return 1
            }
        }
    }
    func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
        if ((addressSelected == true || checkIsPaymentRadioSelect == true) && selected == false){
            if (indexPath.section == 0) {
                return UITableViewAutomaticDimension
            }
            else if (indexPath.section == 1) {
                return 62
            }
            else {
                if height == 0 {
                    return CGFloat(heightStart)
                }
                else{
                    return CGFloat(self.height)
                }
            }
        }
        else{
            if (indexPath.section == 0){
                if self.street?.isEmpty == true{
                    return 50
                }else {
                    return UITableViewAutomaticDimension
                }
            }
            else if (indexPath.section == 1){
                return 62
            }
            else {
                return 0
            }
        }
    }
    func tableView(_ tableView: UITableView, willDisplayHeaderView view: UIView, forSection section: Int){
        let header = view as! UITableViewHeaderFooterView
        header.textLabel?.textColor = UIColor.gray
        header.textLabel?.textAlignment = NSTextAlignment.center
        header.textLabel?.font = UIFont(name: "Futura", size: 17)
    }

Upvotes: 0

Views: 737

Answers (3)

Mohindra Bhati
Mohindra Bhati

Reputation: 156

You can do it by set your Delegate and DataSource in web Service call Back.

DispatchQueue.main.async {
                    self.tableDetails.delegate = self
                    self.tableDetails.dataSource = self
                    self.tableDetails.reloadData()
                }

hope it works.

Upvotes: 0

ozzieozumo
ozzieozumo

Reputation: 436

The tableview will start loading whether your JSON call has finished or not. This happens automatically after viewDidLoad finishes .. it doesn't wait for the reloadData() call in your completion handler.

So you need to setup your numberOfSections to return 0 until the data has been loaded. This way, your table will be empty (and cellForRow will not even be called) until the completion handler puts the data in place and calls reloadData(). At which time, your numberOfSections will return non-zero and your data will be displayed.

Upvotes: 1

Bista
Bista

Reputation: 7893

You should initialize all your variables used inside table view methods with some default values.

Like: var street: String! = "" , var addressSelected: Bool! = false etc.

Because even before the API is called, some of these values are nil or not set.

For cell.nameLabel.text = "\((dict?.firstName)!) \, you can return 0 in numberOfRows method.

guard let _ =  dict {
    return 0
}

Upvotes: 0

Related Questions