我的应用程序的目的是下载WWDC视频的字幕文件。字幕在名为“fileSequence0.webvtt”,“fileSequence1.webvtt”等的WebVTT文件中可用,位于视频和幻灯片文件所在目录的宏子目录中。
如果您有任何WWDC视频(或幻灯片)文件,您可以获取从中下载的URL,删除文件名,并添加必要的额外路径组件以制作字幕URL,然后下载该字幕文件 - 和这就是我的应用程序所做的。
虽然我最初设想了一个双层模型,但我最终得到了一个单一的平面列表,所以我现在只使用大纲视图作为普通表视图 - 没有任何项目有任何子项。
我的商品是下载来源,每个商品都有以下属性:
bool
),此后称为“完成”当我将视频文件提供给我的应用时,它会创建一个下载源,依次生成每个字幕文件的远程URL。我的应用程序下载每个字幕文件,随时更新下载源的状态。
我的应用无法知道有多少字幕文件;它只知道它们已被编号。因此,当它获得404时,它知道它已经下载了该视频文件的所有字幕文件,因此它将下载源标记为完成并继续下一个下载源(如果有的话)。
我的窗口控制器是我的大纲视图的数据源和委托。
大纲视图是基于视图的。在行视图中,四个单元视图中的三个绑定到其对象值的属性:
第四列包含一个图像视图,这就是困难的来源。
因为我不想用“doneImage
”属性污染我的模型(我觉得这是控制器业务),我让控制器在返回单元格视图时设置图像视图的图像:< / p>
- (NSView *) outlineView:(NSOutlineView *)outlineView viewForTableColumn:(NSTableColumn *)tableColumn item:(id)item {
NSTableCellView *cellView = [outlineView makeViewWithIdentifier:tableColumn.identifier owner:self];
PRHVideoFileDownloadSource *downloadSource = item;
cellView.objectValue = downloadSource;
if ([tableColumn.identifier isEqualToString:@"done"]) {
NSLog(@"Source %@ is done: %@", downloadSource, downloadSource.complete ? @"true" : @"false");
cellView.imageView.image = downloadSource.complete ? [NSImage imageNamed:@"Done"] : nil;
}
return cellView;
}
最初,这很好用。 如果我取出测试模型对象是否完成的条件,则完成图像显示(因此我知道正在复制图像,它是一个有效的图标,列的标识符设置正确,等)。
但是,在适当的条件下,即使在下载源变为完成后,图像也不会出现。
你可以看到我添加了一个NSLog。这只出现一次(每行):
2013-07-22 15:46:18.028 WWDC Subtitles Fetcher[7980:1307] Source <PRHVideoFileDownloadSource 0x7fd6f533d340 "404-Advances in Objective-C.pdf"> is done: false
2013-07-22 15:46:18.035 WWDC Subtitles Fetcher[7980:1307] Source <PRHVideoFileDownloadSource 0x10b372190 "405-Interface Builder Core Concepts-SD.mov"> is done: false
通过绑定到单元格视图objectValue
的属性来填充的单元格都可以正常工作。仅此内容视图未绑定的单元格不会更新。
如上所述,我在调用outlineView:viewForTableColumn:item:
时尝试过记录。每行只调用一次;再也不会了。
所以,也许我需要提示它重新加载那些行,对吧?我在标记下载源的行之后立即添加了reloadItem:
消息。没有骰子 - 它肯定已到达(我有另一个错误,因为修复后,当我这样做时导致异常),但是大纲视图没有采取提示并要求我重新创建/更新此视图。
我还尝试将图片视图绑定到单元格视图的objectValue
并实现outlineView:objectValueForTableColumn:byItem:
:
//Revised outlineView:viewForTableColumn:item: that doesn't set the cell view's objectValue
- (NSView *) outlineView:(NSOutlineView *)outlineView viewForTableColumn:(NSTableColumn *)tableColumn item:(id)item {
NSTableCellView *cellView = [outlineView makeViewWithIdentifier:tableColumn.identifier owner:self];
return cellView;
}
//Return the Done image for the “done” column; return the Download Source for all other columns (whose cells' content views are bound to properties of the Download Source)
- (id)outlineView:(NSOutlineView *)outlineView objectValueForTableColumn:(NSTableColumn *)tableColumn byItem:(id)item {
PRHVideoFileDownloadSource *downloadSource = item;
if ([tableColumn.identifier isEqualToString:@"done"]) {
NSLog(@"Source %@ is done: %@", downloadSource, downloadSource.complete ? @"true" : @"false");
return downloadSource.complete ? [NSImage imageNamed:@"Done"] : nil;
}
return downloadSource;
}
虽然这更干净,但我认为我会保留它,但它并没有解决问题 - objectValueForTableColumn:byItem:
方法同样只被调用一次,尽管reloadItem:
,因此没有机会将图像分配为该单元格的新objectValue
。
我需要一种方法(有效)告诉大纲视图“这个特定的行已经改变了;请更新其objectValue
s - 或者更好的方法,告诉它该行中的特定单元格已更改。
答案 0 :(得分:1)
不是返回“完成”列的复选标记图像以及其他列的下载源,而是返回所有列的下载源。然后使用NSNegateBoolean值转换器将图像视图的“隐藏”绑定绑定到下载源的“完整”属性。当模型触发KVO通知时,这将允许图像显示或隐藏自身,因此您不必刷新项目并希望以您希望的方式更新内容。