Reputation: 1449
I'm trying to have my tableview scroll to the bottom after new data is loaded. For example I have a chat window that is loading new messages once my 'sendReply' button is pressed, and I always want it to scroll to the most recent message (at the bottom) when data is posted. For some reason, my tableView won't scroll to the bottom after self.tableview reload?
I assume this is because of rowNumber-1 in my method, but when I try to change this to -0, I get the error:
Terminating app due to uncaught exception 'NSRangeException', reason: '-[UITableView _contentOffsetForScrollingToRowAtIndexPath:atScrollPosition:usingPresentationValues:]: row (16) beyond bounds (16) for section (0).'
ViewController.m
- (void)scrollTableToBottom {
NSInteger rowNumber = [self. tableView numberOfRowsInSection:0];
if (rowNumber > 0) {
[self. tableView scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:rowNumber-1 inSection:0] atScrollPosition:UITableViewScrollPositionBottom animated:YES];
}
}
- (IBAction)sendReply:(id)sender {
if ([self.messageData count] > 0) {
self.sendButton.hidden = YES;
self.activityIndicator.hidden = NO;
[self.activityIndicator startAnimating];
NSMutableDictionary *nodeData = [NSMutableDictionary new];
[nodeData setObject:@"messages" forKey:@"type"];
NSDictionary *messageValues = [NSDictionary dictionaryWithObjects:[NSArray arrayWithObjects:self.replyField.text, nil] forKeys:[NSArray arrayWithObjects:@"value", nil]];
NSDictionary *finalMessage = [NSDictionary dictionaryWithObject:[NSArray arrayWithObject:messageValues] forKey:@"und"];
[nodeData setObject:finalMessage forKey:@"body"];
NSString *otherUID = [self.messageData objectForKey:@"uid"];
NSString *userValue = otherUID;
NSDictionary *targetMessage = [NSDictionary dictionaryWithObjects:[NSArray arrayWithObjects:userValue, nil] forKeys:[NSArray arrayWithObjects:@"value", nil]];
NSDictionary *finalUser = [NSDictionary dictionaryWithObject:[NSArray arrayWithObject:targetMessage] forKey:@"und"];
[nodeData setObject:finalUser forKey:@"field_targetuser"];
[nodeData setValue: @"Re:" forKey:@"title"];
NSDictionary *userDictInfo = (NSDictionary*) [NSKeyedUnarchiver unarchiveObjectWithData:[[NSUserDefaults standardUserDefaults] objectForKey:@"diosSession"]];
DIOSSession *session = [DIOSSession sharedSession];
[session setUser:userDictInfo];
[session user];
NSString *uid = [session user][@"user"][@"uid"];
[DIOSNode nodeSave:nodeData success:^(AFHTTPRequestOperation *operation, id responseObject) {
self.replyField.text = @"";
[self.tableView reloadData];
[self scrollTableToBottom];
self.sendButton.hidden = NO;
[self.activityIndicator stopAnimating];
self.activityIndicator.hidden = YES;
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(@"Node did not save!");
}];
} else if ([self.messageDataFriends count] > 0) {
self.sendButton.hidden = YES;
self.activityIndicator.hidden = NO;
[self.activityIndicator startAnimating];
NSMutableDictionary *nodeData = [NSMutableDictionary new];
[nodeData setObject:@"messages" forKey:@"type"];
NSDictionary *messageValues = [NSDictionary dictionaryWithObjects:[NSArray arrayWithObjects:self.replyField.text, nil] forKeys:[NSArray arrayWithObjects:@"value", nil]];
NSDictionary *finalMessage = [NSDictionary dictionaryWithObject:[NSArray arrayWithObject:messageValues] forKey:@"und"];
[nodeData setObject:finalMessage forKey:@"body"];
NSString *otherUID = [self.messageDataFriends objectForKey:@"uid2"];
NSString *userValue = otherUID;
NSDictionary *targetMessage = [NSDictionary dictionaryWithObjects:[NSArray arrayWithObjects:userValue, nil] forKeys:[NSArray arrayWithObjects:@"value", nil]];
NSDictionary *finalUser = [NSDictionary dictionaryWithObject:[NSArray arrayWithObject:targetMessage] forKey:@"und"];
[nodeData setObject:finalUser forKey:@"field_targetuser"];
[nodeData setValue: @"Re:" forKey:@"title"];
NSString *uid = [[[DIOSSession sharedSession] user] objectForKey:@"uid"];
[DIOSNode nodeSave:nodeData success:^(AFHTTPRequestOperation *operation, id responseObject) {
dispatch_async(dispatch_get_main_queue(), ^{
self.replyField.text = @"";
[self.tableView reloadData];
[self scrollTableToBottom];
self.sendButton.hidden = NO;
[self.activityIndicator stopAnimating];
self.activityIndicator.hidden = YES;
});
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(@"Node did not save!");
}];
}
}
Upvotes: 2
Views: 430
Reputation: 1916
Add to the first block
dispatch_async(dispatch_get_main_queue(), ^{
self.replyField.text = @"";
[self.tableView reloadData];
[self scrollTableToBottom];
self.sendButton.hidden = NO;
[self.activityIndicator stopAnimating];
self.activityIndicator.hidden = YES;
});
Also add NSLog(@"rowNumber = %lu",rowNumber);
after NSInteger
rowNumber = [self.tableView numberOfRowsInSection:0];
in
scrollTableToBottom method. And before [self.tableView reloadData];
If they are equal, this means that the data have not been reloaded yet.
Upvotes: 1