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
}
self.getMoreData()- can you show this part? - Andreas Oetjen