3

我正在實現一個簡單的文件瀏覽器(在NSOutlineView中),並在展開我的根節點時碰到了EXC_BAD_ACCESS。從這個方法返回EXC_BAD_ACCESS在啓用ARC的情況下實現NSOutlineViewDataSource

- (id)outlineView:(NSOutlineView *)outlineView child:(NSInteger)index ofItem:(id)item { 
    if (!item) { 
     // Root node 
     return @"Files"; 
    } 
    NSFileManager *manager = [NSFileManager defaultManager]; 

    NSError *error = nil; 
    return [[manager contentsOfDirectoryAtPath:@"/" error:&error] objectAtIndex:index]; 
} 

NSString被自動釋放,而當了AppKit代碼調用這裏:我NSOutlineViewDataSource回報如下孩子

- (NSView *)outlineView:(NSOutlineView *)outlineView viewForTableColumn:(NSTableColumn *)tableColumn item:(id)item { 
    NSString *identifier = [item isEqualToString:@"Files"] ? @"HeaderCell" : @"DataCell"; 
    NSTableCellView *cell = [outlineView makeViewWithIdentifier:identifier owner:self]; 
    cell.textField.stringValue = item; 
    return cell; 
} 

item已經走了。這是該項目的生命週期的工具截圖:

Instruments Screenshot

我不知道我在做什麼錯 - 我不能明確retain任何東西(也不應我!),因爲ARC已啓用,但兒童用品仍然丟失。

編輯:堆棧跟蹤實際的碰撞:

0 CoreFoundation -[__NSCFString retain] 
    1 Spark -[SPFileBrowserController outlineView:child:ofItem:] /Users/Craig/projects/Spark/Spark/SPFileBrowserController.m:29 
    2 AppKit loadItemEntryLazyInfoIfNecessary 
    3 AppKit -[NSOutlineView _rowEntryForChild:ofParent:requiredRowEntryLoadMask:] 
    4 AppKit -[NSOutlineView _expandItemEntryChildren:atStartLevel:expandChildren:andInvalidate:] 
    5 AppKit -[NSOutlineView _expandItemEntry:expandChildren:startLevel:] 
    6 AppKit -[NSOutlineView _batchExpandItemsWithItemEntries:expandChildren:] 
    7 AppKit -[NSOutlineView expandItem:expandChildren:] 
    8 AppKit -[NSOutlineView _doUserExpandOrCollapseOfItem:isExpand:optionKeyWasDown:] 
    9 AppKit -[NSOutlineView _outlineControlClicked:] 
    10 AppKit -[NSApplication sendAction:to:from:] 
    11 AppKit -[NSControl sendAction:to:] 
    12 AppKit -[NSCell _sendActionFrom:] 
    13 AppKit -[NSCell trackMouse:inRect:ofView:untilMouseUp:] 
    14 AppKit -[NSButtonCell trackMouse:inRect:ofView:untilMouseUp:] 
    15 AppKit -[NSControl mouseDown:] 
    16 AppKit -[NSWindow sendEvent:] 
    17 AppKit -[NSApplication sendEvent:] 
    18 AppKit -[NSApplication run] 
    19 AppKit NSApplicationMain 
    20 libdyld.dylib start 

編輯2:項目現在連接。編輯SPFileUtilchildrenOfFolder:的返回值以使用選項2重複一致。當使用單個NSString時它總是通過,但在使用NSFileManager內容時總是失敗。

https://www.dropbox.com/s/lqj5r5ndg0qusak/Spark.zip

擴大根「文件」項之後發生崩潰。

回答

1

從文件系統直接提供大綱視圖內容可能有點不安全,例如,如果文件系統被添加/刪除,會發生什麼情況?更好的方法是讓您緩存文件系統內容並直接提供內容。然後,可以肯定的是,從值返回:

– numberOfRowsInTableView: 

匹配已存儲的內容(並要求不再存在一排,當你不出去的越界例外)。

要真的很喜歡,你可以觀看文件系統,並刷新緩存,然後更改大綱視圖時,對其進行更改。

UPDATE:繼此,作爲緩存的一部分,你通常建立在大綱視圖中的節點樹,使用的數據結構是這樣的:

@interface OutlineNode : NSObject 
{ 
    id _item; 
    OutlineNode * __weak _parentNode; 
    NSMutableArray *_childNodes; 
} 

,你可以設置在特定節點OutlineView,例如:

- (BOOL)outlineView:(NSOutlineView *)outlineView 
    isItemExpandable:(id)item 
{ 
    if (item == nil) 
     return YES; 

    OutlineNode *node = (OutlineNode *)item; 
    return node.parentNode == nil; 
} 
+0

謝謝!我曾計劃過緩存文件系統並定期刷新(或按照FS事件庫),但這種快速骯髒的方法只是一個佔位符,其好奇的行爲促使我調查而不是繼續前進。此外,stacktrace添加。 –

+0

我添加了一個我的(非常輕量級)項目的副本。我完全被難住了。 (請參閱編輯2) –

相關問題