简体   繁体   中英

iOS, reloadRowsAtIndexPaths - Crashing after i add new object to its Data Source

I have a UITableView, and its data source gets updated from a call to a PHP Script and the response adds a new object to the Array if there is any data to be updated. The call makes a check in the database table if new items have been added via a TimeStamp and if there is new data then the new data will occupy position index at 0 in the array data source but when i use reloadRowsAtIndexPath the app crashes. The reason i want to do it this way is because i don't want to refresh the whole UITableView cells, just keep the existing data and add new data without effecting the existing cells. Now the cell has an image that does lazy loading and every time i add new data the images reload and does not make the app look good when it does this, so thats why i need to refresh new data coming in. This is how i am using this reloadRowsAtIndexPaths:

-(void)renderLastTSPostInfo:(NSDictionary*)dic{


            NSDictionary *posts = [dic objectForKey:@"posts"];

            if((NSNull*)posts != [NSNull null]){
            int counter = 1;
            int p_ID;
            int p_U_ID;
            int p_T_ID;
            NSString *p_Message;
            NSDate *p_Created;
            int p_Flagged;
            int p_Rated;
            NSString *firstNamePost;
            NSString *lastNamePost;
            NSString *p_userImage;

            for(NSDictionary *dict in posts)
            {
                if((NSNull *)[dict objectForKey:@"P_ID"] != [NSNull null]){
                p_ID = [[dict objectForKey:@"P_ID"] intValue];
                }
                if((NSNull *)[dict objectForKey:@"P_U_ID"] != [NSNull null]){
                p_U_ID = [[dict objectForKey:@"P_U_ID"] intValue];
                }
                if((NSNull *)[dict objectForKey:@"P_T_ID"] != [NSNull null]){
                p_T_ID = [[dict objectForKey:@"P_T_ID"] intValue];
                }
                if((NSNull *)[dict objectForKey:@"P_Message"] != [NSNull null]){
                p_Message = [dict objectForKey:@"P_Message"];
                }
                if((NSNull *)[dict objectForKey:@"P_Created"] != [NSNull null]){
                NSString *timestampString = [dict objectForKey:@"P_Created"];
                double timestampDate = [timestampString doubleValue];
                p_Created = [NSDate dateWithTimeIntervalSince1970:timestampDate];
                }
                if((NSNull *)[dict objectForKey:@"P_Flagged"] != [NSNull null]){
                p_Flagged = [[dict objectForKey:@"P_Flagged"] intValue];
                }
                if((NSNull *)[dict objectForKey:@"P_Rated"] != [NSNull null]){
                p_Rated = [[dict objectForKey:@"P_Rated"] intValue];
                }
                if((NSNull *)[dict objectForKey:@"U_FirstName"] != [NSNull null]){
                firstNamePost = [dict objectForKey:@"U_FirstName"];
                }
                if((NSNull *)[dict objectForKey:@"U_LastName"] != [NSNull null]){
                lastNamePost = [dict objectForKey:@"U_LastName"];
                }
                if((NSNull *)[dict objectForKey:@"U_Image"] != [NSNull null]){
                p_userImage = [dict objectForKey:@"U_Image"];
                }

                PostInfo *postObj = [PostInfo new];
                postObj.iD = p_ID;
                postObj.userId  = p_U_ID;
                postObj.threadId = p_T_ID;
                postObj.message = p_Message;
                postObj.timeStampCreated = p_Created;
                postObj.flagged = p_Flagged;
                postObj.rated = p_Rated;
                postObj.firstName = firstNamePost;
                postObj.lastName = lastNamePost;
                postObj.userImage = p_userImage;

                [postsArray insertObject:postObj atIndex:0];

                if(counter == posts.count){
                postLastTimestamp = [dict objectForKey:@"P_Created"];
                }

                counter += 1;

            }
            [tableViewPosts beginUpdates];
            [tableViewPosts reloadRowsAtIndexPaths:[NSArray arrayWithObject:[NSIndexPath indexPathForRow:0 inSection:0]] withRowAnimation:UITableViewRowAnimationFade];
            [tableViewPosts endUpdates];
            //[tableViewPosts reloadData];
            }



        }

Error i get is:

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 (11) must be equal to the number of rows contained in that section before the update (10), 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).'

When I encountered this problem, I was reloading the table view too often and the items weren't yet added to the collection. The solution for me was to call layoutIfNeeded before reloadData and this call will wait until previous batch is drawn before drawing the current one.

[tableViewPosts layoutIfNeeded];

You don't fill the data actively, you just implement the data source delegates.

If the data has changed, use [yourTableView reloadData] to refresh, the table will fetch the data it needs. There are methods for reloading sections or a couple of rows, too, if you know what changed and want to animate this.

Also, make sure to call on the main thread (in case your timer fires on another thread).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM