1
votes

I have used tableView to show the post and when I am scrolling my page sometimes it crashes and throws error as: Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Invalid update: invalid number of rows in section 0. The number of rows contained in an existing section after the update (119) must be equal to the number of rows contained in that section before the update (105), plus or minus the number of rows inserted or deleted from that section (1 inserted, 1 deleted) and plus or minus the number of rows moved into or out of that section (0 moved in, 0 moved out).' I am unable to find out the reason why it's happening

func getFeeds(){
    DispatchQueue.main.async {
        if(self.isCommentsOpened == false && self.spinner == nil && !self.isPaginating && self.isScrollingUp == false){
        self.spinner = CommonUtils.showLoader(view: self)
        }
    }
     var paramsDictionary = [String:Any]()
            let xAuthToken:String=UserDefaults.standard.string(forKey: JsonContants.X_AUTH_TOKEN)!
            let entityId:String=UserDefaults.standard.string(forKey: JsonContants.ENTITY_ID)!
            var apiUrl=domains.global+Apis.feedQueryApi
            apiUrl=apiUrl.replacingOccurrences(of: "{entity_id}", with: entityId)
            if(isPaginating && pageNo<totalPages){
            paramsDictionary[JsonContants.PAGE_NO] = pageNo+1
            paramsDictionary[JsonContants.PAGE_SIZE] = pageSize
            }else{
                paramsDictionary[JsonContants.PAGE_NO] = 1
                paramsDictionary[JsonContants.PAGE_SIZE] = pageSize
            }
            HttpClientApi.instance().makeAPICall(token: xAuthToken,refreshToken: "",url:  apiUrl, params:paramsDictionary, method: .POST, success: { (data, response, error) in
                do {
                    if let json = try JSONSerialization.jsonObject(with: data!, options: .allowFragments) as? [String: Any] {
                        let httpStatus=response as HTTPURLResponse!
                        let statusCode=httpStatus?.statusCode
                        let pageDetails = json[JsonContants.PAGE_DETAILS] as! [String:Any]
                        if(pageDetails.count>0){
                            self.pageNo =  pageDetails[JsonContants.PAGE_NO] as! Int
                            self.pageSize =  pageDetails[JsonContants.PAGE_SIZE] as! Int
                            self.totalPages = pageDetails[JsonContants.TOTAL_PAGES] as! Int
                        }
                        let feedsArray = json[JsonContants.FEEDS] as! Array<Dictionary<String, Any>>
                        if(!self.isPaginating){
                            self.feedsJsonArray = feedsArray
                            self.feedIdsArray = [String]()
                            self.feedIdUserIdDict = [String:String]()
                            self.userIdUserJsonDict = [String:[String:Any]]()
                            self.imagesJsonArray = []
                            self.feedIdActivityJsonDict = [String:[[String:Any]]]()
                        }else{
                            self.paginationFeedIdsArray = [String]()
                            self.feedsJsonArray.append(contentsOf: feedsArray)
                        }
                        var paginationUserIdDict = [String]()
                        for object:Dictionary<String,Any> in feedsArray{
                            let feedId=object[JsonContants.FEED_ID] as? String
                            self.feedIdsArray.append(feedId!)
                            let userId = object[JsonContants.USER_ID] as? String
                            self.feedIdUserIdDict[feedId!] = userId
                            if(self.isPaginating){
                            paginationUserIdDict.append(userId!)
                            self.paginationFeedIdsArray.append(feedId!)
                            }
                        }
                         DispatchQueue.main.async {
                        if(!self.isPaginating){
                        self.getUserList(userIds: Array(self.feedIdUserIdDict.values))
                            self.dismissLoader()
                        }else{
                            self.getUserList(userIds: paginationUserIdDict)
                            self.dismissLoader()
                            }
                        }
                    }
                } catch let error {
                    print(error.localizedDescription)
                    DispatchQueue.main.async {
                        if(self.spinner != nil){
                        self.spinner!.dismissLoader()
                        self.spinner = nil
                        }
                        if((self.topScrollSpinnerContainerView.isHidden == false) ||  (self.downScrollSpinnerContainerView.isHidden == false)){
                            self.scrollSpinner!.dismissLoader2()
                            self.topScrollSpinnerContainerView.isHidden = true
                            self.downScrollSpinnerContainerView.isHidden = true
                        }
                    }
                }
                
            }, failure: { (data, response, error) in
                DispatchQueue.main.async {
                    if(self.spinner != nil){
                    self.spinner!.dismissLoader()
                    self.spinner = nil
                    }
                    if((self.topScrollSpinnerContainerView.isHidden == false) ||  (self.downScrollSpinnerContainerView.isHidden == false)){
                        self.scrollSpinner!.dismissLoader2()
                        self.topScrollSpinnerContainerView.isHidden = true
                        self.downScrollSpinnerContainerView.isHidden = true
                    }
                }
                
                print(error?.localizedDescription as Any)
                
            })
}

func showSmallLoaderAtBottom(view: UIView) -> UIView {

        var spinnerView = UIView(frame: CGRect(x: 0, y: 0, width: 50, height:50))
        let spinner = MDCActivityIndicator(frame: CGRect(x: 0, y: 0, width: 50, height:50))
        spinner.cycleColors = [UIColor(named: AppColors.appSkyBlue.rawValue)!, UIColor(named: AppColors.appSkyBlue.rawValue)!,UIColor(named: AppColors.appSkyBlue.rawValue)!,UIColor(named: AppColors.appSkyBlue.rawValue)!]
        spinnerView.addSubview(spinner)
        view.addSubview(spinnerView)
        spinner.startAnimating()
        return spinnerView
        }

func getMoreData(){
    if(self.pageNo < self.totalPages){
        scrollSpinner = showSmallLoaderAtBottom(view: downScrollSpinnerContainerView)
        downScrollSpinnerContainerView.isHidden = false
        isPaginating = true
        self.getFeeds()
    }
}

 func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    self.currentRow = indexPath.row
    let cell=tableView.dequeueReusableCell(withIdentifier: "feed_tvcell", for: indexPath) as! FeedTableViewCell
    cell.selectionStyle = .none
    cell.feedViewController = self
    cell.feedsStackView.translatesAutoresizingMaskIntoConstraints = false
    
    let feedJson = self.feedsJsonArray[indexPath.row]
    cell.messageTextLabel.numberOfLines = 0
    cell.messageTextLabel.lineBreakMode = .byWordWrapping
    cell.messageTextLabel.sizeToFit()
    if(feedJson[JsonContants.CONTENT] != nil && !(feedJson[JsonContants.CONTENT] as! String).elementsEqual(JsonContants.NA)){
        cell.feedMessageView.isHidden = false
        cell.messageTextLabel.text = (feedJson[JsonContants.CONTENT] as! String).decodeEmoji
    }else{
        cell.feedMessageView.isHidden = true
    }
    let feedId = feedJson[JsonContants.FEED_ID] as! String
    let userId = feedIdUserIdDict[feedId] as! String
    let userJson = userIdUserJsonDict[userId] as? [String:Any]
    var userTitle:[[String:Any]]?
    var lastName:String?
    var firstName:String?
    if(userJson != nil){
        userTitle = userJson![JsonContants.USER_TITLE] as? [[String:Any]]
        lastName = userJson![JsonContants.LAST_NAME] as? String
        firstName = userJson![JsonContants.FIRST_NAME] as? String
    }
    var roles = self.appDefaults.value(forKey: JsonContants.ROLE) as! [String]
    if(firstName != nil){
    cell.feeUserName.text = (firstName as! String)
    }
    if(lastName != nil){
        cell.feeUserName.text = cell.feeUserName.text!+" "+(lastName as! String)
    }
    
    hideAndShowFeedDeleteButton(roles, cell, userId)
    
    addActionTargetsToCellButtons(cell)
    
    var time = feedJson[JsonContants.LAST_ACTIVITY_TIME] as! Int64
    var timeDiff = CommonUtils.getSystemTimeInMillis() - time
    cell.feedTime.text = CommonUtils.getStringValueOfTimeDiff(timeDiff: timeDiff)
    
    setCountZero(cell)
    setLikeCount(feedId, cell, feedJson)
    
    var feedType = feedJson[JsonContants.TYPE] as! String
    
    let feedCommentCount = feedJson[JsonContants.FEED_COMMENT_COUNT] as! Int
    cell.commentCountLabel.text = String(feedCommentCount)
    
    
    if(userJson != nil){
        let userId = userJson![JsonContants.USER_ID] as? String
        var cachedMediaId:UIImage?
        let userJsonFromDb = CoreDataDatabaseManager.coreDataDatabaseManager.getUser(id: userId!)
        if(userJsonFromDb != nil && userJsonFromDb.count>0){
        let imageId = userJsonFromDb[JsonContants.IMAGE_ID] as? String
        if(userId != nil && imageId != nil){
            cachedMediaId  = self.getSavedImage(named : imageId!+"."+"png")
            }
        }
        if(cachedMediaId == nil){
            cell.feedUserImage.image = #imageLiteral(resourceName: "user_default_round")
            getUserImages(userIds: [userId!],cell: cell)
            
        }else{
            cell.feedUserImage.image = cachedMediaId
        }
      
    }else{
        cell.feedUserImage.image = #imageLiteral(resourceName: "user_default_round")
    }
    
    
    if(userJson != nil && userJson![JsonContants.RESIDENT_DETAILS] != nil){
        let residentDetails = userJson![JsonContants.RESIDENT_DETAILS] as! [String:Any]
        let buildingName = residentDetails[JsonContants.BUILDING_NAME] as! String
        let flatName = residentDetails[JsonContants.FLAT_NAME] as! String
        let feedUserName:String = cell.feeUserName.text!
        if(buildingName.count>0 && flatName.count>0){
        cell.feeUserName.text = feedUserName+" - "+buildingName+"("+flatName+")"
        }
    }else if(userTitle != nil && userTitle!.count>0) {
        let titleDict = userTitle![0]
        let name = cell.feeUserName.text
        if(titleDict.count>0){
            var title = titleDict[JsonContants.TITLE] as! String
            if(title.elementsEqual(JsonContants.ADMINISTRATOR)){
            cell.feeUserName.text = name!+" - "+"Admin"
            }
        }
    }
    if(feedType.elementsEqual(JsonContants.SURVEY)){
        let options = feedJson[JsonContants.OPTIONS] as! [[String:Any]]
        setSurveyData(cell, options, feedId, feedJson,indexPath: indexPath)       
        
    }else{
    
    if(feedJson[JsonContants.MEDIA_INFO] != nil && (feedJson[JsonContants.MEDIA_INFO] as! [String:Any]) != nil &&
        (feedJson[JsonContants.MEDIA_INFO] as! [String:Any]).count>0){
       let  mediaJson = feedJson[JsonContants.MEDIA_INFO] as! [String:Any]
        let mediaType = mediaJson[JsonContants.MEDIA_TYPE] as! String
        cell.optionsTableView.isHidden = true
        cell.surveyTotalVotesLabel.isHidden = true
        cell.surveyTotalVotesLabelContainer.isHidden = true
        cell.feedVideoView.isHidden = true
        cell.feedImageView.isHidden = true
        
        if(mediaType.elementsEqual(JsonContants.IMAGE)){
            configureFeedImageViewAndSetImage(cell, mediaJson, feedId,indexPath)
        }else{
            configureFeedMediaViewAndSetVideo(cell, mediaJson, indexPath)
        }
    }else{
        cell.mediaType = "TEXT"
        hideFeedMediaViews(cell)
        cell.layoutIfNeeded()
    }
    
    }
     if(indexPath.row == (self.feedsJsonArray.count-2)){
                DispatchQueue.main.async{
                    self.getMoreData()
                }
     }
    cell.layoutIfNeeded()
    return cell
}
1
I cannot find any problem in the code you posted; the only thing that might cause this is self.getMoreData() - can you show this part? - Andreas Oetjen
ok i m also updating with that function - A J
You need to show that code that adds data to the model / table view, like getFeeds - Andreas Oetjen

1 Answers

0
votes

This kind of error is seen when you explicitly insert or delete cells or sections into or from a TableView and do not simultaneously readjust your row or section counts to match. In your case the error message is telling you exactly what the count mismatch is. The code you posted is not showing any inserts or deletes of rows from the TableView so it must be happening somewhere else in your code, maybe in your getFeeds() method?