Obj-C - 数据重新加载后TableView滚动到底部?

Posted

技术标签:

【中文标题】Obj-C - 数据重新加载后TableView滚动到底部?【英文标题】:Obj-C - TableView scroll to bottom after data reloaded? 【发布时间】:2017-12-09 06:30:56 【问题描述】:

我试图在加载新数据后让我的 tableview 滚动到底部。例如,我有一个聊天窗口,一旦按下“sendReply”按钮,就会加载新消息,并且我总是希望它在发布数据时滚动到最新消息(在底部)。由于某种原因,self.tableview 重新加载后我的 tableView 不会滚动到底部?

我认为这是因为我的方法中有 rowNumber-1,但是当我尝试将其更改为 -0 时,出现错误:

由于未捕获的异常“NSRangeException”而终止应用程序,原因: '-[UITableView _contentOffsetForScrollingToRowAtIndexPath:atScrollPosition:usingPresentationValues:]: 第 (0) 行的第 (16) 行超出界限 (16)。'

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!");
        ];


    



【问题讨论】:

您需要-1,因为最后一行是“count - 1”。你说表格不会滚动到底部。当您调用 scrollTableToBottom 方法时,它实际上做了什么?另外,您是否意识到在对 DIOSNode nodeSave 的 2 次调用中的 1 次中,您没有在主线程上调用 reloadDatascrollTableToBottom @rmaddy 表格滚动到倒数第二个单元格(因此它确实滚动到“底部”,但不是非常底部 - 这是新添加的单元格)。如果我在数据重新加载之前调用 scrollTableToBottom,确实,它会滚动到最底部。 在那之后你可以手动滚动实际的最后一行吗? @rmaddy 是的,我可以 【参考方案1】:

    添加到第一个块

    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;
    );
    

    还在NSInteger rowNumber = [self.tableView numberOfRowsInSection:0]; 之后添加NSLog(@"rowNumber = %lu",rowNumber); scrollTableToBottom 方法。在[self.tableView reloadData];之前 如果它们相等,这意味着数据还没有被重新加载。

【讨论】:

如果是这种情况,我怎么才能让它在加载新数据后才滚动到最底部? @Brittany,我不知道。

以上是关于Obj-C - 数据重新加载后TableView滚动到底部?的主要内容,如果未能解决你的问题,请参考以下文章

更改数据和 popViewController 后 TableView 不会重新加载

JSON请求后以编程方式TableView不会重新加载数据

Swift:在警报视图中按下按钮后,tableView 不会重新加载数据

获取异步 JSON 数据后重新加载 tableview

使用重新加载数据选择子项后,Tableview 刷新到父视图

更改数组后无法在 Tableview 中重新加载数据?