2011-03-17 71 views
2

我正在從SQLite數據庫加載一些數據以顯示在UITableView。爲了確保用戶不被阻塞並且表格被快速顯示,我創建了一個隊列並添加了要在後臺執行的數據庫操作。NSOperationQueue和UITableView

該添加是好的,工作正常,但由於某種原因隨機部分行不更新數據!

我知道數據設置正確,因爲當我點擊行更新我的數據的行,但我似乎無法找到更新用戶界面的方法!我已經嘗試了一切,包括使用setNeedDisplay等,但沒有任何作品!

這裏是我的代碼:

- (UITableViewCell *) tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{ 
    static NSString *CellIdentifier = @"Cell"; 

    UITableViewCell* cell = (UITableViewCell*)[tableView dequeueReusableCellWithIdentifier:CellIdentifier]; 
    if (cell == nil) { 
     cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease]; 
     cell.textLabel.textAlignment = UITextAlignmentRight; 
     cell.textLabel.numberOfLines = 0; 
     cell.textLabel.font = [UIFont systemFontOfSize:14]; 
    } 

    cell.accessoryType = UITableViewCellAccessoryNone; 
    cell.textLabel.text = @"Loading ..."; 
    cell.tag = indexPath.row; 

    NSInvocationOperation *op = [[NSInvocationOperation alloc] initWithTarget:self 
                    selector:@selector(setCellData:) 
                     object:cell]; 

    [queue addOperation:op]; 
    [op release]; 

    return cell; 
} 


- (void) setCellData:(UITableViewCell *)cell{ 

    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; 

    sqlite3_stmt   *statement2; 

    NSString *sqlStr = [NSString stringWithFormat:@"SELECT * FROM poemdata WHERE catid='%d' GROUP BY poemid LIMIT 1 OFFSET %d",catId,cell.tag]; 
// NSLog(@"%@",sqlStr); 
    sqlite3_prepare_v2(database, [sqlStr cStringUsingEncoding:NSASCIIStringEncoding], -1, &statement2, nil); 

    cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator; 
    if(sqlite3_step(statement2) == SQLITE_ROW){ 
     cell.textLabel.text = [[NSString alloc] initWithUTF8String: (char *)sqlite3_column_text(statement2, 3)]; 
     cell.tag = sqlite3_column_int(statement2, 6); 
    }else{ 
     cell.textLabel.text = @"Error"; 
    } 
    sqlite3_finalize(statement2); 

    [pool release]; 
} 

回答

1

您正在從後臺線程更新您的用戶界面,這是錯誤的。所有用戶界面工作必須在主線程上完成。嘗試將所有與cell的交互移動到主線程,將數據從後臺線程傳遞到NSDictionary

請參閱performSelectorOnMainThread:withObject:waitUntilDone:。另請參閱Apple的線程編程指南中的Threads and Your User Interface

@theChrisKent對性能有很好的評價,儘管這個線程問題更可能是您不穩定行爲的原因。

4

你的邏輯是有缺陷的,我想你會遇到可怕的性能,以及您已經遇到的問題。最好是啓動一個整體操作來加載所有數據或至少一部分數據,然後在表完成時重新加載表。

你現在這樣做的方式是,每個單元格都打擊數據庫並選擇一行,而不是將數據緩存到任何位置(這意味着如果它滾動出視圖然後再次返回它將不得不再次訪問數據庫)。此外,操作結束時,不會在該單元格上調用繪圖代碼(這就是爲什麼直到您單擊它纔會顯示繪圖調用時才顯示該代碼)。

您應該將所有這些數據加載到自定義對象的數組中。一旦加載,您應該重新加載表格並使用新填充的數組來設置單元格中的屬性。

+0

那麼問題是大小,這個數據庫是巨大的,所以我不能真正加載我所有的行,加載它的一部分邏輯是最複雜的。所以我需要做我做過的事情。問題是如何才能在屏幕上更新單元格。在你的答案的繪圖部分添加[cell setNeedDisplay]將無濟於事。這裏的問題是計時,單元格在數據設置之前顯示,並且由於某種原因從不刷新。 – Amir 2011-03-17 18:31:48

+1

@Amir如果問題是大小(這不是一個不常見的問題),您將需要實現相同類型的分頁行爲,許多面臨類似問題(無論是來自本地數據庫還是網絡連接)的應用都會這樣做。你應該加載一個大的初始集合(比如100-200條記錄取決於你的單元格佈局的複雜性),然後當用戶到達列表底部加載另一個25-50並釋放第一個25-50時保持一個滾動窗口在記憶中。這不像試圖讓你的發佈代碼工作那麼複雜。 – theChrisKent 2011-03-17 18:42:51

+0

謝謝克里斯,我會考慮改變我的邏輯:)這說我仍然想知道爲什麼這是行不通的! – Amir 2011-03-17 18:44:54