2010-11-22 4 views
0

NSTableView가 배열 컨트롤러 (사전 배열 관리)에 바인딩 된 간단한 인터페이스를 초기화하고 있습니다. 배열에 대한 내용을 백그라운드에서로드하려고합니다 (시간이 많이 소요되는 프로세스입니다). 100 또는 1000 개 요소마다 테이블 뷰를 업데이트하고 싶습니다. 아이디어는 인터페이스가 사용 가능하고 반응 적이라는 것입니다. 나중에 업데이트/새로 고침을 트리거하는 방법을 알 수 없습니다. 테이블은 비어 있습니다. 누구든지 포인터를 제공 할 수 있습니까? 난 그냥 직접 데이터를로드, 백그라운드에서 모든 것이 잘 작동 그렇게하려고하지 않는 경우인터페이스를 차단하지 않고 NSTableView에 대한 데이터를로드하려면 어떻게해야합니까?

// In init for my app controller. This seems to work well, but I've tried other methods here. 
[self performSelectorInBackground:@selector(loadTable) withObject:nil]; 


- (void)loadTable { 
    tracks = [[NSMutableArray alloc] initWithCapacity:[masters count]]; 

    // ... create each object one-by-one. Add it to tracks. 
    for (... in ...) { 
    [tracks addObject:newObject]; 
    } 

    // Now I don't know what to do next. The table remains empty. 
    // Things I've tried (though possibly not in all combinations with the 
    // method above): 
    // 1. With a suitably-defined reloadData method, which just reloads 
    // the table view and sets needs display. 
    [self performSelectorOnMainThread:@selector(reloadData) withObject:nil waitUntilDone:YES]; 

    // 2. Reload directly. 
    [tv reloadData]; 
    [tv setNeedsDisplay]; 
} 

하지만 거의 30 대를 취합니다

내 현재의 접근 방식이다.

답변

6

배열 컨트롤러에 바인딩 된 테이블 열 (사용자가 의도 한 것으로 가정)이 있으므로 테이블 뷰에서 해당 데이터를 가져옵니다. 테이블 뷰는 업데이트 된 배열을 요청할 수 있지만 어레이 컨트롤러에 변경 사항을 알지 못한다.

어레이 컨트롤러는 단순히 돌아 서서 새로운 데이터를 요청하지 않습니다. 이는 테이블 뷰를 배열에 바인딩하는 것이 더 어려워지기 위해서만 존재한다는 것을 암시합니다. 그것은 컨트롤러입니다. 그 일은 배열을 소유하고 그 순서와 그 객체의 일부 하위 집합의 사용자 선택을 유지하는 것입니다.

따라서 어레이에 항목을 추가 할 때 알기 위해서는 어레이 컨트롤러가 필요합니다. 이 작업을 수행하는 가장 좋은 방법은 어레이 컨트롤러의 contentArray을 컨트롤러의 속성에 바인딩하고 해당 속성을 KVO 호환 방식으로 업데이트하는 것입니다.

의미 :

  1. init 방법의 변경 가능한 배열을 만듭니다. 에
  2. the array accessor methods 플러스 addTracksObject:removeTracksObject: (이는 기술적으로 설정된 접근 자 메서드이므로 KVO는 배열 속성에 대해 무시합니다).
  3. 트랙을 추가하려면 addTracksObject: 메시지를 보내십시오. 메시지에 insertObject:inTracksAtIndex: 메시지를 보내야합니다 (색인을 작성하려는 경우가 아니면 색인에 [self countOfTracks]). tracks 배열에 insertObject:atIndex: 메시지를 보내어 insertObject:inTracksAtIndex:에 응답해야합니다. foo가있는 NSArray 속성 때 그 배열 접근이기 때문에 당신이 insertObject:inFooAtIndex:removeObjectFromFooAtIndex:의 상단에이를 구현해야하므로 KVO는, 그에만 NSSet - 속성 접근을 고려, addFooObject:removeFooObject:을 무시

내가 언급 한 바와 같이, 이는 KVO가 그들에게 반응 할 것임을 의미합니다.

3 단계는 배열 컨트롤러가 속성을 다시 가져오고 테이블보기를 사용하여 배열 컨트롤러의 arrangedObjects을 모든 행에 대해 적어도 한 번 다시 페치하도록하기 때문에 매우 느립니다. 당신은 더합니다.

  • insertTracks:atIndexes:을 구현하고, 그것을 (예 : 100 또는 1000) 트랙 중 하나 개 배치의 배열을 전달하고 인덱스 세트 :

    그래서, 당신이 다른 3 단계로 배치 추가 동작을 유지해야한다 [NSIndexSet indexSetWithRange:(NSRange){ [self countOfTracks], countOfBatch }]으로 구성됩니다. 또한 removeTracksAtIndexes:을 구현해야합니다. KVO가 해당 삽입 메소드가 없어도 KVO가 각 삽입 메소드를 무시할 것이기 때문입니다.

어레이 컨트롤러가 선택을 유지하도록 설정해야합니다. 그래야 행을 가져 오는 동안 사용자를 너무 많이 좌절시키지 않게 될 것입니다.

또한 메인 스레드 수행을 사용하여 추가 할 일괄 처리를 주기적으로 보내고 백그라운드 스레드에 개체를 생성 할 수 있습니다. 나는 일반적으로 주 스레드 실행 루프를 가능한 한 수행하는 옹호자이지만 정기적 인로드가 다른 배치를 빌드하는 동안 이런 종류의 일은 쉽게 느린 인터페이스를 만들 수 있습니다.

1

메인 스레드의 테이블보기에서 setNeedsDisplay:YES으로 전화해야합니다. 백그라운드 스레드에서 호출하지 마십시오. 모든 코코아 UI 호출은 주 스레드에서 수행해야합니다. 그렇지 않으면 이상한 일이 발생합니다.

관련 문제