簡體   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