Reputation: 65
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
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
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
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