그래서, 이에 대한 대답은 심장 약한되지 않습니다. 그 이유는 NSTableView가 자연스럽게 원하지 않는 일을하기 위해서입니다.
코코아의 기본 NSTableView는 여러 선택 동작 이용하여 시작 를 - 행을 클릭하면 그것을 선택하고 다른 행 이 선택 해제 - 제어를 들고와 열을 클릭 만
이제 행의 선택 상태를 전환, 체크 박스 열을 추가하십시오. 이 행에 대한 규칙은 다릅니다 : - 확인란을 클릭하면 해당 행의 선택 상태가 토글됩니다
클릭 수를 캡처하여 직접 처리 할 수 있다면 간단합니다. 이제는 문제를 해결할 수 있지만 문제는 NSTableView로 계속 전달되어 일반적인 방법으로 선택을 변경한다는 것입니다. [참고 :이 전달을 피할 수있는 방법이있을 수 있습니다. 알고 계시면 알려주세요.]
다음과 같이 수행 할 수 있습니다. - 각 개체에 'selectedInView'입력란 추가 기본 객체 배열에 있습니다. keyPath : "selectedObjects"에 대한 옵서버를 연관된 NSArrayController에 추가합니다. 선택 영역이 변경되면 각 객체에 대해 selectedInView 필드를 설정합니다. 이런 식으로 뭔가 : 이미 선택이 존재 때 체크 박스 오작동이 유일한 시간 :
if([keyPath isEqualToString:@"selectedObjects"]) {
// For table view checkbox's: keep "selectedInView" of song dictionaries up to date
[_arrayController.arrangedObjects enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
BOOL sel = [_arrayController.selectedObjects containsObject:obj];
if([[obj objectForKey:@"selectedInView"] boolValue] != sel)[obj setValue:[NSNumber numberWithBool:sel] forKey:@"selectedInView"];
}];
이제 까다로운 부분이 온다. 다음은 사례 유형입니다.
설정 : 행의 1,2,3가 선택됩니다. 확인란 4 행을 클릭했습니다. 결과 : 네 번째 행의 확인란이 선택되었습니다. 네 번째 행이 선택됩니다. 행의 1,2,3 선택을 취소합니다 (NSTableView가 자연스럽게 수행하기 때문에)
이 문제를 해결하려면 확인란을 클릭 할 때마다 현재 선택 항목을 기억하기 위해 임시 배열을 생성해야합니다. 클릭 다음의 tableview 그것의 선택 처리를 수행하고있다
- (void)tableView:(NSTableView *)tableView setObjectValue:(id)object forTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)row {
if([tableColumn.identifier isEqualToString:@"CheckBox"]) {
NSMutableDictionary *song = [_arrayController.arrangedObjects objectAtIndex:row];
if(!_tempSelectedSongs && _arrayController.selectedObjects) _tempSelectedSongs = [[NSMutableArray arrayWithArray:_arrayController.selectedObjects] retain];
if(_tempSelectedSongs) {
if([_tempSelectedSongs containsObject:song]) {
[_tempSelectedSongs removeObject:song];
} else if(![_tempSelectedSongs containsObject:song]) {
[_tempSelectedSongs addObject:song];
}
}
}
}
이제 한 후, 우리는 그것이 있어야 무엇을 선택을 설정합니다. 실제로 선택을 수행하기 전에 테이블 뷰 선택을 수정할 수있는 유망한보고 기능이 있습니다.당신과 같이 수정할 수 있습니다 : 이것은 위대한 작품을
- (NSIndexSet *)tableView:(NSTableView *)tableView selectionIndexesForProposedSelection:(NSIndexSet *)proposedSelectionIndexes {
NSMutableIndexSet *newSet = [NSMutableIndexSet indexSet];
if(_tempSelectedSongs) {
NSMutableIndexSet *indexSet = [NSMutableIndexSet indexSet];
[_tempSelectedSongs enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
NSUInteger index = [_arrayController.arrangedObjects indexOfObject:obj];
if(index != NSNotFound) [indexSet addIndex:index];
}];
proposedSelectionIndexes = indexSet;
[_tempSelectedSongs release]; _tempSelectedSongs = nil; [_tempSelectedSongsTimer invalidate]; [_tempSelectedSongsTimer release]; _tempSelectedSongsTimer = nil;
}
[proposedSelectionIndexes enumerateIndexesUsingBlock:^(NSUInteger idx, BOOL *stop) {
NSProgressIndicator *progress = ((BDDiscreteProgressCell *)[[_arrayController.arrangedObjects objectAtIndex:idx] objectForKey:@"BDCell"]).progress;
if(!progress)
[newSet addIndex:idx];
}];
return newSet;
}
, 그러나 NSTableView는 위임 함수가 호출되는 순서에 문제가있는 것입니다. 분명히 우리는 첫 번째 함수, 즉 임시 배열을 설정하는 두 번째 함수를 두 번째 함수보다 먼저 호출해야합니다. 여기서 우리는 정보를 사용합니다.
어떤 이유로 든 체크 박스를 DE- 선택하면 이것이 작동하는 방식이며 이지만 확인란을 선택하면 반대가 발생합니다.
if([keyPath isEqualToString:@"selectedObjects"]) {
if(_tempSelectedSongs) {
_arrayController.selectedObjects = _tempSelectedSongs;
[_tempSelectedSongs release]; _tempSelectedSongs = nil;
}
// For table view checkbox's: keep "selectedInView" of song dictionaries up to date
[_arrayController.arrangedObjects enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
BOOL sel = [_arrayController.selectedObjects containsObject:obj];
if([[obj objectForKey:@"selectedInView"] boolValue] != sel)[obj setValue:[NSNumber numberWithBool:sel] forKey:@"selectedInView"];
}];
}
편집 :이 경우에 그래서, 당신은 당신의 위의 키 패스의 관찰자에게 좀 더 많은 코드를 추가 할 수 있습니다 추가하는 경우가 밝혀 : 하나의 행이 선택되는 경우는 체크 박스가 있어요 "클릭되지 않은,"이 수행 자동으로 selectedObjects 알림을 트리거하지 않으므로 새 선택을 구현하기 위해 타이머에서 함수를 실행해야합니다.