2009-09-20 70 views
2

我試圖得到一個大綱視圖來顯示一個目錄,現在我編輯了從蘋果的例子,使其工作從我設置的任何目錄,除了擴展任何節點時,我得到「EXEC_BAD_ACCESS」來自NSOutlineView類。EXC_BAD_ACCESS當使用NSOutlineView

這裏是頭文件:

#import <Cocoa/Cocoa.h> 

@interface SMLDirectoryDataSource : NSObject { 
    NSString *rootDirectory; 
} 

- (int)outlineView:(NSOutlineView *)outlineView numberOfChildrenOfItem:(id)item; 
- (BOOL)outlineView:(NSOutlineView *)outlineView isItemExpandable:(id)item; 
- (id)outlineView:(NSOutlineView *)outlineView 
      child:(int)index 
      ofItem:(id)item; 
- (id)outlineView:(NSOutlineView *)outlineView objectValueForTableColumn:(NSTableColumn *)tableColumn 
      byItem:(id)item; 
- (void) setRootDirectory:(NSString *)directory; 

@end 

@interface SMLDirectoryDataItem : NSObject 
{ 
    NSString *relativePath, *fullPath; 
    SMLDirectoryDataItem *parent; 
    NSMutableArray *children; 
} 

//+ (SMLDirectoryDataItem *)rootItem; 
- (int)numberOfChildren;// Returns -1 for leaf nodes 
- (SMLDirectoryDataItem *)childAtIndex:(int)n;// Invalid to call on leaf nodes 
- (NSString *)fullPath; 
- (NSString *)relativePath; 

@end 

這裏是實現文件:

#import "SMLDirectoryDataSource.h" 


@implementation SMLDirectoryDataSource 
- (id)initWithDirectory:(NSString *)path 
{ 
    rootDirectory = path; 
    return self; 
} 

- (int)outlineView:(NSOutlineView *)outlineView numberOfChildrenOfItem:(id)item 
{ 
    return (item == nil) ? 1 : [item numberOfChildren]; 
} 

- (BOOL)outlineView:(NSOutlineView *)outlineView isItemExpandable:(id)item 
{ 
    return (item == nil) ? NO : ([item numberOfChildren] != -1); 
} 

- (id)outlineView:(NSOutlineView *)outlineView 
      child:(int)index 
      ofItem:(id)item 
{ 
    NSLog(@"hi there"); 
    if(rootDirectory == nil) 
      rootDirectory = @"/"; 
    NSLog(rootDirectory); 
    if(item == nil){ 
     SMLDirectoryDataItem *item = [[SMLDirectoryDataItem alloc] initWithPath:rootDirectory parent:NULL]; 
     return item; 
     [item release]; 
    } 
    else 
     return [(SMLDirectoryDataItem *)item childAtIndex:index]; 
} 
/*(
- (id)outlineView:(NSOutlineView *)outlineView 
objectValueForTableColumn:(NSTableColumn *)tableColumn 
      byItem:(id)item 
{ 
    if(rootDirectory == nil) 
     rootDirectory = @"/"; 
    return rootDirectory; 
} 
*/ 
- (void)setRootDirectory:(NSString *)directory 
{ 
    rootDirectory = directory; 
} 

- (id)outlineView:(NSOutlineView *)outlineView objectValueForTableColumn:(NSTableColumn *)tableColumn byItem:(id)item { 
    if(item == nil) 
     return rootDirectory; 
    else 
     return (id)[(SMLDirectoryDataItem *)item relativePath]; 
} 

- (BOOL)outlineView:(NSOutlineView *)outlineView shouldEditTableColumn:(NSTableColumn *)tableColumn item:(id)item { 
    return NO; 
} 

@end 

@implementation SMLDirectoryDataItem 

//static SMLDirectoryDataItem *rootItem = nil; 
#define IsALeafNode ((id)-1) 

- (id)initWithPath:(NSString *)path parent:(SMLDirectoryDataItem *)obj 
{ 
    fullPath = [path copy]; 
    if (self = [super init]) 
    { 
     relativePath = [[path lastPathComponent] copy]; 
     parent = obj; 
    } 
    return self; 
} 


/*+ (SMLDirectoryDataItem *)rootItem 
{ 
    if (rootItem == nil) rootItem = [[SMLDirectoryDataItem alloc] initWithPath:@"/" parent:nil]; 
    return rootItem; 
}*/ 


// Creates, caches, and returns the array of children 
// Loads children incrementally 
- (NSArray *)children 
{ 
    if (children == NULL) { 
     NSFileManager *fileManager = [NSFileManager defaultManager]; 
     //NSString *fullPath = [self fullPath]; 
     BOOL isDir, valid = [fileManager fileExistsAtPath:fullPath isDirectory:&isDir]; 
     if (valid && isDir) { 
      NSArray *array = [fileManager contentsOfDirectoryAtPath:fullPath error:NULL]; 
      if (!array) { // This is unexpected 
       children = [[NSMutableArray alloc] init]; 
      } else { 
       NSInteger cnt, numChildren = [array count]; 
       children = [[NSMutableArray alloc] initWithCapacity:numChildren]; 
       NSString *filename = [[NSString alloc] init]; 
       for (cnt = 0; cnt < numChildren; cnt++) { 
        filename = [fullPath stringByAppendingPathComponent:[array objectAtIndex:cnt]]; 
        SMLDirectoryDataItem *item = [[SMLDirectoryDataItem alloc] initWithPath:filename parent:self]; 
        [children addObject:item]; 
        [item release]; 
       } 
       [filename release]; 
      } 
     } else { 
      NSLog(@"is a leaf... strange"); 
      children = IsALeafNode; 
     } 
    } 
    return children; 
} 


- (NSString *)relativePath 
{ 
    return relativePath; 
} 


- (NSString *)fullPath 
{ 
    // If no parent, return our own relative path 
    //if (parent == nil) return relativePath; 

    // recurse up the hierarchy, prepending each parent’s path 
    //return [[parent fullPath] stringByAppendingPathComponent:relativePath]; 
    return fullPath; 
} 

- (SMLDirectoryDataItem *)childAtIndex:(int)n 
{ 
    return [[self children] objectAtIndex:n]; 
} 

- (int)numberOfChildren 
{ 
    id tmp = [self children]; 
    return (tmp == IsALeafNode) ? (0) : [tmp count]; 
} 


- (void)dealloc 
{ 
    if (children != IsALeafNode) [children release]; 
    [relativePath release]; 
    [super dealloc]; 
} 

@end 

更新:更新了最新版本的代碼

回答

7

你是不是正確管理內存。

(1)這行代碼泄漏。自動釋放SMLDirectoryDataItem實例。

return (item == nil) ? [[SMLDirectoryDataItem alloc] initWithPath:rootDirectory parent:nil] : [item childAtIndex:index]; 

(2)在您的-initWithPath:parent:方法中,以下代碼行不保留字符串。自動釋放池在耗盡時釋放它。這是最有可能導致您的崩潰:

relativePath = [path lastPathComponent]; 

評論此:

http://developer.apple.com/mac/library/DOCUMENTATION/Cocoa/Conceptual/MemoryMgmt/MemoryMgmt.html

有代碼(更新後的代碼)的一些其他問題:

(1)第一最重要的是,這...

#define IsALeafNode ((id)-1) 

.... is complet是錯的。你將-1傳遞給期望對象的東西。如果有任何保留/自動發佈或其他消息,則立即崩潰。

(2)此外,您仍然沒有正確管理內存。您的-setRootDirectory:方法不保留該字符串。我會建議使用@property和@snthesizing setter/getter。

(3)你的-children方法像篩子一樣漏出字符串。具體來說,文件名變量的用法是錯誤的。

+0

好,所以我改變了它,所以它不會崩潰,但現在它說「[__NSCFType numberOfChildren]:無法識別的選擇器發送到實例」 – kennyisaheadbanger 2009-09-20 18:32:29

+0

然後,你將不得不做一些調試。打破-outlineView:numberOfChildrenOfItem:並查看項目的價值和等級。然後確定項目的類別是如何成爲它的。 – 2009-09-20 21:37:36

+0

現在我真的很困惑..我已經複製了更新的示例中的東西,現在的方法objectValueForTableColumn正在使它崩潰,即使它被調用大約4次事先和經營好吧... if(item == nil )由於某種原因不工作! – kennyisaheadbanger 2009-09-22 12:52:48

相關問題