참고 : 비슷한 문제에 대해 스택 오버플로를 검색했으며이 특정 문제를 해결하는 것으로 보이는 질문이 없습니다.NSTableView reloadData 메서드를 사용하면 모든 행의 NSProgressIndicator가 업데이트되고 깜박입니다.
내가 (여기에 해당 소스 코드를 완료 Xcode 프로젝트 : http://jollyroger.kicks-ass.org/stackoverflow/FlickeringTableView.zip를) 작은 샘플 응용 프로그램을 작성했습니다 /System/Library/Sounds/
순차적으로 모든 사운드를 재생하고 그들이 문제를 보여주기 위해 재생과 같은 창에서 소리를 표시 I 보고 있습니다. MainMenu.xib
의 창은 세 항목 셀 템플릿으로 정의 된 하나의 행으로 단일 열 NSTableView
이 있습니다
NSTextField
- 가 개최하는 또 다른
NSTextField
사운드 정보를 보유 할 - 소리 이름
- 소리가 나는
NSTableCellView
이 (SoundsTableCellView.h
)는 셀의 각 항목을 경쟁 정의하는 서브 클래스했다
를 재생하는 동안 NSProgressIndicator
플레이 진행률을 표시합니다 시간이 생길 때 나는 그들을 액세스하고 설정할 수 있습니다.
AVAudioPlayer
API를 통해 사운드 파일 재생을 처리하는 데 필요한 속성과 메서드를 캡슐화하는 MySound
클래스를 정의했습니다. 이 클래스는 MySoundDelegate
프로토콜을 정의하여 사운드가 시작되거나 끝날 때마다 앱 델리게이트가 이벤트를 수신 할 수있게합니다.
애플리케이션 대리인 필요할 때 그 관련 정보 테이블 MySound
객체 배열의 테이블 데이터를 저장 및 업데이트 할 수 있도록하고 NSTableViewDelegate
NSTableViewDataSource
프로토콜을 준수. 또한 소리가 시작되거나 끝날 때 이벤트를 수신하기 위해 MySoundDelegate
프로토콜을 준수합니다. 대리자에는 refreshWindow
메서드를 주기적으로 호출하여 현재 재생중인 사운드의 진행률 표시기를 업데이트하는 NSTimer
작업도 있습니다.
앱 위임자의 refreshWindow
메서드는 목록의 사운드 수에 따라 필요한 경우 창을 표시하고 크기를 조정하고 재생되는 사운드에 대한 저장된 참조를 연결된 NSProgressIndicator
으로 업데이트합니다.
앱 델리게이트의 tableView: viewForTableColumn
(NSTableViewDelegate
프로토콜) 메소드가 호출되어 표 셀을 채 웁니다.
- 체크 나는 테이블 컬럼에 대한 인터페이스 빌더 (엑스 코드)에 설정된는 식별자 (
sound column
)과 일치 보장하기 위해 테이블 열 식별자 : 그것은, 나는 조언 "테이블보기 프로그래밍을 채우기"애플의 표준을 사용 , - 는
thisTableView makeViewWithIdentifier
를 호출 식별자 (sound cell
)와 해당 테이블 셀을 얻을 - 후, 을 데이터 소스 (APP 대리자
- 는
NSTextFields
의 스트링 값을 설정하고maxValue
과 관련된 사운드 객체의 대응하는 세부 셀 내의NSProgressIndicator
의doubleValue
, - 저장소 나중에 업데이트 관련된 사운드 객체에 연관된
sounds
어레이)의 정합 어레이 소자 를 찾기 위해 수신
row
매개 변수를 사용하여
NSProgressIndicator
제어 기준을 설정할 여기
- (NSView *)tableView:(NSTableView *)thisTableView viewForTableColumn:(NSTableColumn *)thisTableColumn row:(NSInteger)thisRow
{
SoundsTableCellView *cellView = nil;
// get the table column identifier
NSString *columnID = [thisTableColumn identifier];
if ([columnID isEqualToString:@"sound column"])
{
// get the sound corresponding to the specified row (sounds array index)
MySound *sound = [sounds objectAtIndex:thisRow];
// get an existing cell from IB with our hard-coded identifier
cellView = [thisTableView makeViewWithIdentifier:@"sound cell" owner:self];
// display sound name
[cellView.soundName setStringValue:[sound name]];
[cellView.soundName setLineBreakMode:NSLineBreakByTruncatingMiddle];
// display sound details (source URL)
NSString *details = [NSString stringWithFormat:@"%@", [sound sourceURL]];
[cellView.soundDetails setStringValue:details];
[cellView.soundDetails setLineBreakMode:NSLineBreakByTruncatingMiddle];
// update progress indicators
switch ([sound state])
{
case kMySoundStateQueued:
break;
case kMySoundStateReadyToPlay:
break;
case kMySoundStatePlaying:
if (sound.playProgress == nil)
{
sound.playProgress = cellView.playProgress;
}
NSTimeInterval duration = [sound duration];
NSTimeInterval position = [sound position];
NSLog(@"row %ld: %@ (%f/%f)", (long)thisRow, [sound name], position, duration);
NSLog(@" %@: %@", [sound name], sound.playProgress);
[cellView.playProgress setMaxValue:duration];
[cellView.playProgress setDoubleValue:position];
break;
case kMySoundStatePaused:
break;
case kMySoundStateFinishedPlaying:
break;
default:
break;
}
}
return cellView;
}
그리고 여기 refreshWindow
방법입니다 :
- (void) refreshWindow
{
if ([sounds count] > 0)
{
// show window if needed
if ([window isVisible] == false)
{
[window makeKeyAndOrderFront:self];
}
// resize window to fit all sounds in the list if needed
NSRect frame = [self.window frame];
int screenHeight = self.window.screen.frame.size.height;
long maxRows = ((screenHeight - 22)/82) - 1;
long displayedRows = ([sounds count] > maxRows ? maxRows : [sounds count]);
long actualHeight = frame.size.height;
long desiredHeight = 22 + (82 * displayedRows);
long delta = desiredHeight - actualHeight;
if (delta != 0)
{
frame.size.height += delta;
frame.origin.y -= delta;
[self.window setFrame:frame display:YES];
}
// update play position of progress indicator for all sounds in the list
for (MySound *nextSound in sounds)
{
switch ([nextSound state])
{
case kMySoundStatePlaying:
if (nextSound.playProgress != nil)
{
[nextSound.playProgress setDoubleValue:[nextSound position]];
NSLog(@" %@: %@ position: %f", [nextSound name], nextSound.playProgress, [nextSound position]);
}
break;
case kMySoundStateQueued:
case kMySoundStateReadyToPlay:
case kMySoundStatePaused:
case kMySoundStateFinishedPlaying:
default:
break;
}
}
}
else
{
// hide window
if ([window isVisible])
{
[window orderOut:self];
}
}
// reload window table view
[tableView reloadData];
}
는 init
동안, 응용 프로그램 대리인이 해당 폴더에 AIFF 사운드 파일의 목록을 얻을 수있는 /System/Library/Sounds/
폴더를 검색하고 해당 폴더에있는 소리의 각 사운드 객체를 들고 sounds
배열을 만듭니다. 그런 다음 applicationDidFinishLaunching
메서드는 목록에서 첫 번째 사운드를 순차적으로 재생하기 시작합니다.
문제 (샘플 프로젝트를 실행하여 볼 수 있음)는 현재 재생중인 사운드의 맨 위 테이블 행을 업데이트하는 것이 아니라 의 모든 진행률 표시자인 다음 행 중 모두이 업데이트되고 플리커도. 표시 방식이 다소 일치하지 않습니다 (때로는 모두 깜박이고 때로는 예상대로 비어 있습니다). 하지만 업데이트 및 깜박일 때 진행 표시기는 현재 재생중인 사운드와 대략 일치하는 것처럼 보입니다. 그래서 나는이 문제가 어떻게 든 테이블을 업데이트하는 방식과 관련이 있어야한다는 것을 확신합니다. 나는 그 문제가 어디 있는지 어떻게 해결할 지 모를 뿐이다.
어떤 아이디어 또는 지침을 크게 감상 할 수있다 :
여기에 윈도우가 당신에게 아이디어를주고 같은 모습의 스크린 샷입니다!
FYI : Apple의 "프로그래밍 방식으로 테이블보기 채우기"설명서는 https://developer.apple.com/library/content/documentation/Cocoa/Conceptual/TableView/PopulatingView-TablesProgrammatically/PopulatingView-TablesProgrammatically.html –
' makeViewWithIdentifier : owner :' "지정된 식별자를 가진 새로운 **보기 **를 반환합니다." 모든 사운드는 동일한 컨트롤을 가리킬 수 있습니다. – Willeke
고마워요, @Willeke. 확인해 보니 진행 표시기가 실제로 각 행마다 다릅니다. 나는'makeViewWithIdentifier' 메쏘드의'NSLog' 문을 추가하여 주어진 사운드 객체에 대한 저장된 참조를'NSProgressIndicator'에 출력했습니다. 다음은 몇 가지 샘플 출력입니다 : 바소 [] 불어 [] 병 [] 개구리 [] –