NSOutlineView示例

13
请问,您能否提供一个简单完整的Cocoa应用程序示例,其中包含带有分层数据表示的NSOutlineView,不像NSOutlineView和NSTreeController示例那样模棱两可。
谢谢!

这是一个谷歌是你的朋友的例子。有很多相关的示例。 - Chris Gregg
5
那就给我发个链接吧,Chris。我也找了好久都没找到一个做得好的。 - Lothar
2个回答

19

这个例子使用一个简单的双层次结构,其中有两个父节点Foo和Bar,它们各自有两个子节点,分别为Foox,Fooz以及Barx,Barz。轮廓视图是默认视图,只有两列,并且第二列的标识符设置为“children”。

NSDictionary *firstParent = @{@"parent": @"Foo", @"children": @[@"Foox", @"Fooz"]};
NSDictionary *secondParent = @{@"parent": @"Bar", @"children": @[@"Barx", @"Barz"]};
NSArray *list = @[firstParent, secondParent];

- (BOOL)outlineView:(NSOutlineView *)outlineView isItemExpandable:(id)item
{        
    if ([item isKindOfClass:[NSDictionary class]]) {
        return YES;        
    }else {
        return NO;
    }
}

- (NSInteger)outlineView:(NSOutlineView *)outlineView numberOfChildrenOfItem:(id)item
{    

    if (item == nil) { //item is nil when the outline view wants to inquire for root level items
        return [list count];                 
    }   

    if ([item isKindOfClass:[NSDictionary class]]) {
        return [[item objectForKey:@"children"] count];
    }

    return 0;
}

- (id)outlineView:(NSOutlineView *)outlineView child:(NSInteger)index ofItem:(id)item
{

    if (item == nil) { //item is nil when the outline view wants to inquire for root level items
        return [list objectAtIndex:index];                   
    }

    if ([item isKindOfClass:[NSDictionary class]]) {
        return [[item objectForKey:@"children"] objectAtIndex:index];
    }     

    return nil;
}

- (id)outlineView:(NSOutlineView *)outlineView objectValueForTableColumn:(NSTableColumn *)theColumn byItem:(id)item
{          

    if ([[theColumn identifier] isEqualToString:@"children"]) {
        if ([item isKindOfClass:[NSDictionary class]]) {
            return [NSString stringWithFormat:@"%i kids",[[item objectForKey:@"children"] count]];
        }  
        return item;
    }else{
        if ([item isKindOfClass:[NSDictionary class]]) {
            return [item objectForKey:@"parent"];                         
        }           
    }

    return nil;
}

screenshot


4
但是这个问题从未提到过Cocoa Bindings。 - Lothar
我意识到这个问题早就有人回答了,但这是一个非常有用的例子。然而,当我将这个例子插入到我的代码中作为一个测试时,我发现outlineView :: numberOfChildrenOfItem和outlineView:child:ofItem实际上被调用,并且字典项已经按预期初始化,但outlineVIew :: objectValueForTableColumn:byItem从未被调用。因此,父母或子项的任何文本标题都不会显示在行中(行存在,但为空)。可能的原因是什么? - SMGreenfield

5

使用NSURL和Swift的NSOutlineView简单示例,填充目录结构。

AppDelegate.swift

import Cocoa

@NSApplicationMain
class AppDelegate: NSObject, NSApplicationDelegate {


    var mainWindowController: MainWindowController?

    func applicationDidFinishLaunching(aNotification: NSNotification) {
        // Insert code here to initialize your application
        let mainWindowController = MainWindowController()
        mainWindowController.showWindow(self)
        self.mainWindowController = mainWindowController

    }

    func applicationWillTerminate(aNotification: NSNotification) {
        // Insert code here to tear down your application
    }

    func applicationShouldTerminateAfterLastWindowClosed(sender: NSApplication) -> Bool {
        return true
    }
}

FileItem.swift

class FileItem {
    var url: NSURL!
    var parent: FileItem?
    var isLeaf:Bool = false
    static let fileManager = NSFileManager.defaultManager()
    static let requiredAttributes = [NSURLIsDirectoryKey]
    static let options: NSDirectoryEnumerationOptions = [.SkipsHiddenFiles, .SkipsPackageDescendants, .SkipsSubdirectoryDescendants]


    lazy var children: [FileItem]? = {
        if let enumerator = fileManager.enumeratorAtURL(self.url, includingPropertiesForKeys:FileItem.requiredAttributes, options: FileItem.options, errorHandler: nil) {

            var files = [FileItem]() 

            while let localURL = enumerator.nextObject() as? NSURL {
                do {
                    let properties = try localURL.resourceValuesForKeys(FileItem.requiredAttributes)
                    // check this
                    files.append(FileItem(url: localURL, parent: self, isLeaf: (properties[NSURLIsDirectoryKey] as! NSNumber).boolValue))
                } catch {
                    print("Error reading file attributes")
                }
            }
            return files
        }
        return nil
    }()

    init(url: NSURL, parent: FileItem?, isLeaf: Bool){
        self.url = url
        self.parent = parent
        self.isLeaf = isLeaf
    }

    var displayName: String {
        get {
            return self.url.lastPathComponent!
        }
    }

    var count: Int {
        return (self.children?.count)!
    }

    func childAtIndex(n: Int) -> FileItem? {
        return self.children![n]
    }
}

我正在使用MainWindowController,它不需要从AppDelegate中提供窗口或IBOutlet。
import Cocoa

class MainWindowController: NSWindowController {

    @IBOutlet weak var outline: NSOutlineView!
    private var rootItem: FileItem? = FileItem(url: NSURL(fileURLWithPath:"/"), parent: nil, isLeaf: true)

    override func windowDidLoad() {
        super.windowDidLoad()

        // Implement this method to handle any initialization after your window controller's window has been loaded from its nib file.
    }

    override var windowNibName: String? {
        return "MainWindowController"
    }
}

//MARK: - NSOutlineViewDelegate
extension MainWindowController: NSOutlineViewDelegate {

    func outlineView(outlineView: NSOutlineView, viewForTableColumn tableColumn: NSTableColumn?, item: AnyObject) -> NSView? {
        let view = outline.makeViewWithIdentifier("TextCell", owner: self) as? NSTableCellView
        if let it = item as? FileItem {
            if let textField = view?.textField {
                textField.stringValue = it.displayName
            }
        } else {
            if let textField = view?.textField {
                textField.stringValue = self.rootItem!.displayName
            }
        }
        return view
    }
}

//MARK: - NSOutlineViewDataSource
extension MainWindowController: NSOutlineViewDataSource {

     func outlineView(outlineView: NSOutlineView, child index: Int, ofItem item: AnyObject?) -> AnyObject {
        if let it = item as? FileItem {
            return it.childAtIndex(index)!
        }
        return rootItem!
    }
    func outlineView(outlineView: NSOutlineView, numberOfChildrenOfItem item: AnyObject?) -> Int {
        if let it = item as? FileItem {
            return it.count
        }
        return 1
    }
    func outlineView(outlineView: NSOutlineView, isItemExpandable item: AnyObject) -> Bool {
        if let it = item as? FileItem {
            if it.count > 0 {
                return true
            }
        }
        return false
    }
}

这里有一个示例 OutlineView

这是这个示例的修改版本 NSOutlineViewInSwift


1
func outlineView(outlineView: NSOutlineView, child index: Int, ofItem item: AnyObject?) -> AnyObject is a method in NSOutlineViewDataSource, not NSOutlineViewDelegate - YangXiaoyu

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接