繁体   English   中英

单击按钮后重新加载TableView数据

[英]Reload TableView data after click button

我正在进行聊天应用程序并从SQLite数据库中读取消息数据。 我想在点击“发送”按钮后用新消息重新加载我的TableView数据。 我按钮的事件:

    [_sendButton addTarget:self action:@selector(saveMessage:) forControlEvents:UIControlEventTouchUpInside];

我想我需要使用-(void)viewDidAppear:(BOOL)animated但它不起作用(或者我做错了)。

[_tableView reloadData];

-(void)viewDidAppear:(BOOL)animated {

sqlite3 *database;

databaseName = @"Messenges.db";
NSArray *documentPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDir = [documentPaths objectAtIndex:0];
databasePath = [documentsDir stringByAppendingPathComponent:databaseName];

messenges = [[NSMutableArray alloc] init];

if(sqlite3_open([databasePath UTF8String], &database) == SQLITE_OK) {
    const char *sqlStatement = "select * from messenges";
    sqlite3_stmt *compiledStatement;
    if(sqlite3_prepare_v2(database, sqlStatement, -1, &compiledStatement, NULL) == SQLITE_OK) {
        while(sqlite3_step(compiledStatement) == SQLITE_ROW) {
            NSString *dbMessageText = [NSString stringWithUTF8String:(char *)sqlite3_column_text(compiledStatement, 1)];

            Message *messege = [[Message alloc] initWithName:dbMessageText];

            [messenges addObject:messege];

            [messege release];
        }
    }
    sqlite3_finalize(compiledStatement);

}
sqlite3_close(database);}

编辑这是我向TableView添加新行的方法。 单击“发送”按钮后,必须立即添加新行。

-(IBAction)insertRows:(id)sender {
    MDAppDelegate *appDelegate = (MDAppDelegate *)[[UIApplication sharedApplication] delegate];
    [messenges insertObject:[[NSString alloc] initWithFormat:@"%@", _textField.text] atIndex:appDelegate.messenges.count+1];
    NSArray *insertIndexPaths = [NSArray arrayWithObject: [NSIndexPath indexPathForRow:1 inSection:1]];
    UITableView *tV = (UITableView *)self.tableView;

    [tV beginUpdates];
    [tV insertRowsAtIndexPaths:insertIndexPaths withRowAnimation:UITableViewRowAnimationRight];
    [tV endUpdates];}

但是这段代码给了我错误: 'Invalid table view update. The application has requested an update to the table view that is inconsistent with the state provided by the data source.' 'Invalid table view update. The application has requested an update to the table view that is inconsistent with the state provided by the data source.' 我该如何解决?

EDIT2

好。 我只有一节。 numberOfSectionsInTableView:不需要更正。

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
    MDAppDelegate *appDelegate = (MDAppDelegate *)[[UIApplication sharedApplication] delegate];
    NSUInteger numberOfRowsInSection = appDelegate.messenges.count; //add new variable to what rows will be +1
    if (self.editing) {
        numberOfRowsInSection++;
    }
    return numberOfRowsInSection;}

但我仍然有同样的错误。

编辑#3

我们看看吧。 我将insertRows更改为:

-(IBAction)insertRows:(id)sender {
    MDAppDelegate *appDelegate = (MDAppDelegate *)[[UIApplication sharedApplication] delegate];
    [self.tableView beginUpdates];
    self.tableView.editing = YES;
    [messenges insertObject:[[NSString alloc] initWithFormat:@"%@", _textField.text] atIndex:appDelegate.messenges.count+1];

    NSArray *insertIndexPaths = [NSArray arrayWithObject: [NSIndexPath indexPathForRow:appDelegate.messenges.count+1 inSection:1]];
    [self.tableView insertRowsAtIndexPaths:insertIndexPaths withRowAnimation:UITableViewRowAnimationRight];
    [self.tableView endUpdates];
}  

numberOfRowsInSection

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
    MDAppDelegate *appDelegate = (MDAppDelegate *)[[UIApplication sharedApplication] delegate];
    NSUInteger numberOfRowsInSection = appDelegate.messenges.count;
    if (self.tableView.editing) {
           numberOfRowsInSection++;
    }
    NSLog(@"%i",numberOfRowsInSection);
    return numberOfRowsInSection;
}

但是我收到错误*** Terminating app due to uncaught exception 'NSRangeException', reason: '*** -[__NSArrayM objectAtIndex:]: index 4 beyond bounds [0 .. 3]' 然后我纠正了if (self.tableView.editing)

if (self.tableView.editing) {
    MDAppDelegate *someNewDelegate = (MDAppDelegate *)[[UIApplication sharedApplication] delegate];
    numberOfRowsInSection = someNewDelegate.messenges.count+1; //or .count
}

但是有关'NSRangeException'的错误。

要使用动画更新UITableView ,您需要:

  1. UITableView上调用beginUpdates
  2. 更新您的数据模型
  3. 插入/删除行和节
  4. UITableView上调用endUpdates

记住几件事:

  • 如果要删除某个部分,则不应该删除该部分中的行(不必要,甚至可能导致错误)
  • 如果要插入一个部分,则不应该在该部分中插入行( UITableView将调用numberOfRowsInSection:后跟cellForRowAtIndexPath:如果单元格可见)。

你的意思是什么,更新我的数据模型?

如果您通过添加和删除行和节来操作UITableView ,那么您应该有一些方法可以在任何给定时刻跟踪UITableView中当前的哪些节/行。

例如,您应该有一个类似于以下的numberOfRowsInSection:方法:

- (NSInteger)numberOfRowsInSection:(NSInteger)section
{
    // You should have a way to get section data with an index (section)
    // The below example assumes an NSArray named self.mySectionCollection
    // exists for this purpose
    NSArray *sectionList = self.mySectionCollection;
    // You should have data associated with a section.  Below its assumed
    // this data is wrapped in an NSDictionary.  Data that might be in here
    // could include a height, a name, number of rows, etc...
    NSDictionary *sectionData = [sectionList objectAtIndex:section];

    NSInteger rowCount = 0;
    // SectionData should NEVER be nil at this point.  You could raise an
    // exception here, have a debug assert, or just return 0.
    if (sectionData)
    {
        rowCount = [[sectionData objectForKey:@"rowCount"] intValue];
    }
    return rowCount;
}

您可以使用几种不同的方式存储有关节/行的信息,包括使用CoreData。 关键是通过在beginUpdatesendUpdates之间修改此集合,您告诉UITableView如何更新自身(它将根据需要查询numberOfRowsInSection:numberOfSectionscellForRowAtIndexPath:

编辑

我相信如果你修改你的insertRows:方法来修改你的数据源( messenges ),同时你通知UITableView发生了更新,事情将开始正常工作。

尝试使用此代码:

-(IBAction)insertRows:(id)sender 
{
   MDAppDelegate *appDelegate = (MDAppDelegate *)[[UIApplication sharedApplication] delegate];
   UITableView *tV = (UITableView *)self.tableView;

   [tV beginUpdates];

   // UPDATE DATA MODEL IN BETWEEN beginUpdates and endUpdates
   int rowIndex = appDelegate.messenges.count + 1;
   [messenges insertObject:[[NSString alloc] initWithFormat:@"%@", _textField.text] 
                   atIndex:rowIndex];

   // Notify UITableView that updates have occurred
   NSArray *insertIndexPaths = [NSArray arrayWithObject: 
                                [NSIndexPath indexPathForRow:rowIndex inSection:1]];
   [tV insertRowsAtIndexPaths:insertIndexPaths 
             withRowAnimation:UITableViewRowAnimationRight];

   [tV endUpdates];
}

编辑#2

如果您仍然遇到问题,我会查看您在哪里设置self.editing标志。

- (NSInteger)tableView:(UITableView *)tableView 
 numberOfRowsInSection:(NSInteger)section 
{
    MDAppDelegate *appDelegate = (MDAppDelegate *)[[UIApplication sharedApplication] delegate];
    //add new variable to what rows will be +1
    NSUInteger numberOfRowsInSection = appDelegate.messenges.count; 
    if (self.editing) 
    {
        numberOfRowsInSection++;
    }
    return numberOfRowsInSection;
}

此标志控制表中是否存在其他行。 因此,您必须在beginUpdatesendUpdates之间进行beginUpdates ,例如:

// assuming the editing flag is set from some IBAction
-addNewRow:(id)sender
{
   int row = ???;  // not sure where you want this new row

   [self.tableView beginUpdates]
   self.editing = YES;
   NSArray *insertIndexPaths = [NSArray arrayWithObject: 
                                [NSIndexPath indexPathForRow:row inSection:1]];
   [self.tableView insertRowsAtIndexPaths:insertIndexPaths
                         withRowAnimation:UITableViewRowAnimationRight];
   [self.tableView endUpdates];
}

请记住同样调用deleteRowsAtIndexPaths:withRowAnimation:如果用户在删除添加的行时停止编辑。 我相信如果编辑成为永久性的,则不需要采取任何操作,但是你需要设置self.editing = NO同时在self.messenges添加一个新行。

另外 ,在你的insertRows:方法中,你告诉UITableView你在索引1插入一行,实际上你总是在messenges集合的末尾插入。 我修改了我的insertRows方法版本,以便它有一个rowIndex变量,以确保在更新数据模型和通知UITableView更改时使用相同的索引。

最后,请在遇到问题时尽可能多地包含调试信息。 通常当您以尝试的方式更新UITableView时出现问题时,它会告诉您存在不一致错误。 我已经看过它已经有一段时间了,但是在更新表之前有5行数,之后有7行时只添加了1行。 如果它出现在您的控制台中,我希望看到此消息。

编辑#3

这是对您所看到的错误的回应:

*由于未捕获的异常'NSRangeException'终止应用程序,原因:'* - [__ NSArrayM objectAtIndex:]:索引4超出边界[0 .. 3]'

您的错误与插入UITableView无关。 它与您尝试插入超出数组边界的事实有关。 我的猜测是违规行:

[messenges insertObject:[[NSString alloc] initWithFormat:@"%@", 
                          _textField.text] 
                atIndex:appDelegate.messenges.count+1];

要插入数组的末尾,请使用appDelegate.messenges.count的索引(删除+1 )。

另外......您是否完全确定您的数据模型和更新UITableView的调用是否一致? 尝试调用NSLog(@"rowsBeforeUpdate: %i", [self numberOfRowsInSection:0]); 刚刚调用beginUpdates ,就在调用endUpdates之前。 此外,在通知UITableView插入操作时,调用NSLog(@"inserting index paths: %@", insertIndexPaths) 我的猜测是self.messenges准确地反映了表中应该包含的行,但是当self.tableView.editing为true时,通过添加+1 ,你将numberOfRowsInSection:推送到你在insertRowsAtIndexPaths:withRowAnimation:调用中报告的内容insertRowsAtIndexPaths:withRowAnimation:

试试这个:

-(IBAction)insertRows:(id)sender {
    MDAppDelegate *appDelegate = (MDAppDelegate *)[[UIApplication sharedApplication] delegate];
    [self.tableView beginUpdates];
    NSLog(@"rows before update: %i", [self numberOfRowsInSection:0]);

    self.tableView.editing = YES;
    NSLog(@"rows with editing flag set: %i", [self numberOfRowsInSection:0]);

    int rowIndex = appDelegate.messenges.count;  // don't need +1 at end
    int sectionIndex = 0;  // should it be 0 or 1?  I would guess 0
    [messenges insertObject:[[NSString alloc] initWithFormat:@"%@", _textField.text] 
                    atIndex:rowIndex];

    NSArray *insertIndexPaths = [NSArray arrayWithObject:
                                 [NSIndexPath indexPathForRow:rowIndex 
                                                    inSection:sectionIndex]];
    [self.tableView insertRowsAtIndexPaths:insertIndexPaths 
                          withRowAnimation:UITableViewRowAnimationRight];
    NSLog(@"inserting index paths: %@", insertIndexPaths);

    [self.tableView endUpdates];
}

我更改了上面的行索引以排除其中的+1 我将section index更改为0,这应该是正确的,除非这个UITableView确实有多个未提及的部分。 确保您的日志有意义。 如果你看到numberOfRowsInSection:insertRows:过程中增加2 insertRows:那么你最好还是看看insertRowsAtIndexPaths: 反映同样的事情 我很困惑你为什么需要编辑标志来在numberOfRowsInSection:方法中添加另一行。 这部分(如果设置了self.editing ,你添加一个额外的行)似乎没有正常工作。 也许只是尝试省略这部分以使其中的一部分工作,然后一旦你有一些正常工作将其添加回来。 也许更改numberOfRowsInSection:如下所示:直到某些事情开始工作:

- (NSInteger)tableView:(UITableView *)tableView 
 numberOfRowsInSection:(NSInteger)section 
{
    MDAppDelegate *appDelegate = (MDAppDelegate *)[[UIApplication sharedApplication] delegate];
    NSUInteger numberOfRowsInSection = appDelegate.messenges.count;
    NSLog(@"numberOfRowsInSection %i: %u", section, numberOfRowsInSection);
    return numberOfRowsInSection;
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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