2011-03-17 5 views
2

UITableView에 표시 할 SQLite 데이터베이스의 일부 데이터를로드하고 있습니다. 사용자가 차단되지 않고 테이블이 빨리 표시되는지 확인하기 위해 대기열을 만들고 데이터베이스 작업을 추가하여 백그라운드에서 실행합니다.NSOperationQueue 및 UITableView

추가 기능은 정상적으로 작동하지만 정상적으로 작동하지만 일부 이유로 인해 일부 행이 데이터로 업데이트되지 않습니다!

행을 클릭하면 행이 내 데이터로 업데이트되지만 UI를 업데이트하는 방법을 찾지 못하는 것처럼 데이터가 올바르게 설정되어 있다는 것을 알고 있습니다! 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

+1

@Amir 문제가 크기가 아닌 경우 (흔하지 않은 문제는 아닙니다) 동일한 유형의 페이징 동작을 구현하려는 경우 로컬 데이터베이스 또는 네트워크 연결에서 발생하든 비슷한 문제가있는 많은 응용 프로그램에서 발생합니다. 큰 초기 세트 (셀 레이아웃의 복잡성에 따라 100-200 레코드)를로드해야하고 사용자가 목록 하단에 도달하면 다른 25-50을로드하고 처음 25-50을 롤링 윈도우로 유지해야합니다 메모리에. 게시 된 코드를 작동시키는 것만 큼 복잡한 것은 아닙니다. – theChrisKent

+0

크리스, 고맙습니다. 내 논리를 변경하는 방법을 고려해 보겠습니다. :) 저는 아직도 이것이 작동하지 않는 이유를 알고 싶습니다. – Amir