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

Rom*_*use 3 sqlite objective-c tableview ios

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

    [_sendButton addTarget:self action:@selector(saveMessage:) forControlEvents:UIControlEventTouchUpInside];
Run Code Online (Sandbox Code Playgroud)

我想我需要使用,-(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);}
Run Code Online (Sandbox Code Playgroud)

编辑 这是我向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];}
Run Code Online (Sandbox Code Playgroud)

但是这段代码给了我错误:'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;}
Run Code Online (Sandbox Code Playgroud)

但我仍然有同样的错误.

编辑#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];
}  
Run Code Online (Sandbox Code Playgroud)

而且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;
}
Run Code Online (Sandbox Code Playgroud)

但是我收到了一个错误*** 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
}
Run Code Online (Sandbox Code Playgroud)

但是有关'NSRangeException'的错误.

Sam*_*Sam 7

要更新UITableView动画,您需要:

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

记住几件事:

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

如果您UITableView通过添加和删除行和部分来操作a ,那么您应该有一些方法来跟踪当前在哪个部分/行中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;
}
Run Code Online (Sandbox Code Playgroud)

您可以使用几种不同的方式存储有关节/行的信息,包括使用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];
}
Run Code Online (Sandbox Code Playgroud)

编辑#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;
}
Run Code Online (Sandbox Code Playgroud)

此标志控制表中是否存在其他行.出于这个原因,你必须将其与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];
}
Run Code Online (Sandbox Code Playgroud)

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];
Run Code Online (Sandbox Code Playgroud)

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

另外......您是否完全确定您的数据模型和更新UITableView的调用是否一致?NSLog(@"rowsBeforeUpdate: %i", [self numberOfRowsInSection:0]);在呼叫之后beginUpdates和呼叫之前尝试调用endUpdates.此外,NSLog(@"inserting index paths: %@", insertIndexPaths)在通知UITableView插入操作时调用.我的猜测是self.messenges准确地反映了表中应该包含的行,但是通过添加+1when self.tableView.editing为true,您可以将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];
}
Run Code Online (Sandbox Code Playgroud)

我更改了上面的行索引以排除其中+1的内容.我将section index更改为0,这应该是正确的,除非这个UITableView确实有多个未提及的部分.确保您的日志有意义.如果你看到numberOfRowsInSection:在这个过程中增加了两个,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;
}
Run Code Online (Sandbox Code Playgroud)