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

时间:2012-03-22 16:18:33

标签: objective-c ios sqlite tableview

我正在进行聊天应用程序并从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.' 我该如何解决?

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'的错误。

1 个答案:

答案 0 :(得分:7)

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

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

    要记住的事情:

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

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

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

    例如,您应该使用类似于此的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:numberOfSections,和cellForRowAtIndexPath:根据需要)。

    修改

    我相信,如果您修改了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之间进行设置,如:

    // 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的末尾插入{1}}集合。我修改了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准确地反映了表格中应该包含的行,但是当+1为真时添加self.tableView.editing,您可以将numberOfRowsInSection:推到报告的上方您拨打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,那么您最好还看到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;
    }