Yasheed Mohammed
Yasheed Mohammed

Reputation: 212

App crashing when loading tableview with the error "Invalid update: invalid number of sections."

App crashes and shows the following error:

Invalid update: invalid number of sections. The number of sections contained in the table view after the update (6) must be equal to the number of sections contained in the table view before the update (3), plus or minus the number of sections inserted or deleted (0 inserted, 0 deleted).' Please Help

My code:

func numberOfSections(in tableView: UITableView) -> Int {

    return newsArray.count

}

func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {

    return 1
}

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {


    let cell = tableView.dequeueReusableCell(withIdentifier: "CellID", for: indexPath) as? NewsTableViewCell


    cell?.contentView.backgroundColor = UIColor.clear

    let whiteRoundedView : UIView = UIView(frame: CGRect(x: 10, y: 4, width: self.view.frame.size.width - 20, height: 410))

    whiteRoundedView.layer.backgroundColor = CGColor(colorSpace: CGColorSpaceCreateDeviceRGB(), components: [1.0, 1.0, 1.0, 0.9])
    whiteRoundedView.layer.masksToBounds = false
    whiteRoundedView.layer.cornerRadius = 2.0
    whiteRoundedView.layer.shadowOffset = CGSize(width: -1, height: 1)
    whiteRoundedView.layer.shadowOpacity = 0.2

    cell?.contentView.addSubview(whiteRoundedView)
    cell?.contentView.sendSubview(toBack: whiteRoundedView)

    let newsdata = newsArray[indexPath.section]

    let date = NSDate(timeIntervalSince1970: TimeInterval(newsdata.meta))
    let dayTimePeriodFormatter = DateFormatter()
    dayTimePeriodFormatter.dateFormat = "MMM dd YYYY "

    let dateString = dayTimePeriodFormatter.string(from: date as Date)


    print(dateString)

    if let newsImg = self.newsImageCache.object(forKey: indexPath.section as AnyObject){
        cell?.imageOut.image = newsImg as? UIImage
    } else {
        loadImageFromWeb(uri: newsdata.photo, cache: self.newsImageCache, indexpath: indexPath)

    }
    cell?.titleLabel.text = newsdata.title
    cell?.descLabel.text = newsdata.body


    return cell!
}




 func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {

    if indexPath.section + 3 == self.newsArray.count {

        loadDatafromUrl()
    }
}



func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
    return 20
}

// Make the background color show through
func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
    let headerView = UIView()
    headerView.backgroundColor = UIColor.clear
    return headerView
}



func loadDatafromUrl(){
    let uri = "http://localhost/unani-info/admin/json/news.php"
    print(uri)
    if let url = URL(string: uri){

        let config = URLSessionConfiguration.default
        config.requestCachePolicy = .reloadIgnoringLocalAndRemoteCacheData
        let session = URLSession(configuration: config)

        let task = session.dataTask(with: url, completionHandler: {

            (rawData,response,error) in

            if error != nil {
                print("Couldnt load data")
                print(error?.localizedDescription as Any)

            } else {
                if let data = rawData {
                    do{
                        if let json = try JSONSerialization.jsonObject(with: data, options: .allowFragments) as? [AnyObject]{

                            for index in 0...json.count-1 {

                                if let datas = json[index] as? [String: AnyObject] {

                                    let newsObj = News()
                                    newsObj.title = datas["title"] as! String
                                    newsObj.body = datas["body"] as! String
                                    let photo = datas["photo"] as! String
                                    let photourl = "http://localhost/unani-info/admin/uploads/" + photo
                                    newsObj.photo = photourl
                                    newsObj.meta = datas["meta"] as! Int

                                    self.newsArray.append(newsObj)


                                }

                            }
                            DispatchQueue.main.async {
                                self.tableView.reloadData()
                            }

                        }
                    }catch{
                        print("error")
                    }
                }
            }
        })
        task.resume()
    }

}

Upvotes: 2

Views: 814

Answers (2)

pesch
pesch

Reputation: 1996

You are inverting the numberOfSections and numberOfRowsInSection. You should have:

func numberOfSections(in tableView: UITableView) -> Int {
    return 1
}

func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    return newsArray.count
}

Upvotes: 1

iWheelBuy
iWheelBuy

Reputation: 5689

Can you please try:

DispatchQueue.main.async {
    for index in 0...json.count-1 {
        if let datas = json[index] as? [String: AnyObject] {
            let newsObj = News()
            newsObj.title = datas["title"] as! String
            newsObj.body = datas["body"] as! String
            let photo = datas["photo"] as! String
            let photourl = "http://localhost/unani-info/admin/uploads/" + photo
            newsObj.photo = photourl
            newsObj.meta = datas["meta"] as! Int
            self.newsArray.append(newsObj)
        }
    }
    self.tableView.reloadData()
}

Instead of:

for index in 0...json.count-1 {
    if let datas = json[index] as? [String: AnyObject] {
        let newsObj = News()
        newsObj.title = datas["title"] as! String
        newsObj.body = datas["body"] as! String
        let photo = datas["photo"] as! String
        let photourl = "http://localhost/unani-info/admin/uploads/" + photo
        newsObj.photo = photourl
        newsObj.meta = datas["meta"] as! Int
        self.newsArray.append(newsObj)
    }
}
DispatchQueue.main.async {
    self.tableView.reloadData()
}

Upvotes: 1

Related Questions