6

リストされたオブジェクトのカスタム ヘッダー グループ (親ノード) を持つ NSOutlineVew を作成しようとしています。(注: 私はセルベースの NSOutlineView を持っています)。たとえば、Xcode の「Navigator」または Numbers サイドバーのように見えます。カテゴリごとの分離プロパティにデフォルトのグループを使用しましたが、希望どおりではないようです。視覚的に調整できる親ノード (セル) が必要です (コントロール要素と画像を追加します)。

オブジェクトの配列を NSDictionary に渡し、各グループに特定のキーを与えることで、これを実行しようとしました。その結果、NSLog を介してすべてが正しく表示されますが、プログラム NSoulineView のソースとしてのこの変数の転送は失敗します。

ProjectViewController.h

@interface ProjectViewController : NSViewController <NSOutlineViewDataSource, NSObject> {
    IBOutlet NSOutlineView          *outlineView;
    FSEntity                        *content;
}

@property (readonly, assign) NSMutableArray *objects;

@end

ProjectViewController.m

@implementation ProjectViewController

- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {
    self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
    if (self) {
        // Initialization code here.    
        // Setting default path to the local file or directory
        NSString *home = NSHomeDirectory();
        NSURL *url = [[NSURL alloc] initFileURLWithPath:home];
        content = [[FSEntity alloc] initWithURL:url];

        [self defineContentNSOutlineView];
        NSLog(@"Array: %@",_objects);

        // Basic сonfiguration an instance NSOutlineView
        [self configurationNSOutlineView];
    } return self;
}

@synthesize objects = _objects;

- (id)outlineView:(NSOutlineView *)outlineView child:(NSInteger)index ofItem:(id)item {
    return (item == nil) ? [content.children objectAtIndex:index] : [((FSEntity *)item).children objectAtIndex:index];
}

- (BOOL)outlineView:(NSOutlineView *)outlineView isItemExpandable:(id)item {
    return (item == nil) ? content.children.count > 0 : ((FSEntity *)item).children.count > 0;
}

- (NSInteger)outlineView:(NSOutlineView *)outlineView numberOfChildrenOfItem:(id)item {
    return (item == nil) ? content.children.count : ((FSEntity *)item).children.count;
}

- (id)outlineView:(NSOutlineView *)outlineView objectValueForTableColumn:(NSTableColumn *)tableColumn byItem:(id)item {
    if ([item isKindOfClass:[FSEntity class]]) {
        return [((FSEntity *)item) title];
    }

    return nil;
}

- (void)outlineView:(NSOutlineView *)outlineView willDisplayCell:(id)cell forTableColumn:(NSTableColumn *)tableColumn item:(id)item {
    if ([cell isKindOfClass:[ImageAndTextCell class]]) {
        ImageAndTextCell *textField = (ImageAndTextCell *)cell;
        [textField setImage:[item icon]];
    }
}

- (void)defineContentNSOutlineView {
    NSMutableArray *objects = [NSMutableArray arrayWithObjects:[NSDictionary dictionaryWithObjectsAndKeys:@"FINDER", @"title", [NSArray arrayWithObjects:[NSDictionary dictionaryWithObject:content.children forKey:@"title"], nil], @"children",[NSNumber numberWithBool:YES], @"header", nil], nil];
    _objects = objects;
}

- (void)configurationNSOutlineView {
    [outlineView sizeLastColumnToFit];
    [outlineView setFloatsGroupRows:NO];
    [outlineView reloadData];
    [outlineView expandItem:nil expandChildren:YES];
}

@end

それがどのように見えるかを簡単に想像できるように、スキームで示しました。

                 +--------------------------------------------+
                 |  ▼ FINDER FILES                        ₪ ✱ |
                 |      03143553.file                         |
                 |    ▶ Desktop                               |
                 |    ▶ Documents                             |
                 |    ▶ Downloads                             |
                 |    ▶ Movies                                |
                 |    ▶ Music                                 |
                 |    ▶ Pictures                              |
                 +--------------------------------------------+

そして私が今持っているもの(NSTreeControllerを使わないNSoulineView);

                 +--------------------------------------------+
                 |      03143553.file                         |
                 |    ▶ Desktop                               |
                 |    ▶ Documents                             |
                 |    ▶ Downloads                             |
                 |    ▶ Movies                                |
                 |    ▶ Music                                 |
                 |    ▶ Pictures                              |
                 +--------------------------------------------+

Appleの「SourceView」の例については知っていますが、作成されたグループ、オブジェクトの配列(ファイルとフォルダー)に追加する方法がわかりません。NSTreeContollerは階層の最初の要素のみを表示します(インクルードなし):

                 +--------------------------------------------+
                 |  ▼ FINDER FILES                            |
                 |      03143553.file                         |
                 |      Desktop                               |
                 |      Documents                             |
                 |      Downloads                             |
                 |      Movies                                |
                 |      Music                                 |
                 |      Pictures                              |
                 +--------------------------------------------+

SourceView の例の変更された方法:

- (void)addFinderSection {
    [self addFolder:@"FINDER FILES"];

    NSError *error = nil;
    NSEnumerator *urls = [[[NSFileManager defaultManager] contentsOfDirectoryAtURL:self.url includingPropertiesForKeys:[NSArray arrayWithObjects: nil] options:(NSDirectoryEnumerationSkipsHiddenFiles) error:&error] objectEnumerator];
    for (NSURL *url in urls) {
        BOOL isDirectory;
        if ([[NSFileManager defaultManager] fileExistsAtPath:[url path] isDirectory:&isDirectory]) {
            if (isDirectory) {
                [self addChild:[url path] withName:NO selectParent:YES];
            } else {
                [self addChild:[url path] withName:NO selectParent:YES];   
            }
        }
    }

    [self selectParentFromSelection];
}

このメソッドは、後者のスキームに示されているように、最初のオブジェクトのみを表示します。

もう 1 つの質問は、前に述べたように、ノード ** "FINDER FILES" ** ボタンをセルの右側に追加する方法です。

これで私を助けてもらえますか?それほど難しいことではないかもしれませんが、Objective-C を学び始めたばかりで、これを行う方法がわかりません。ありがとう。

4

1 に答える 1

1

あなたが提供した開始コードに基づいて、CellベースのNSOutlineViewsを使用して何かを機能させることができました。あなたが投稿したコードは不完全であるように見えたので、不足しているFSEntityクラスから何を取得したいかを正確に知ることは困難でした。私はファンデーションクラスを使用しました:ノード(つまりルートノードと子)のリスト用のNSArray、各ノード自体(ルートノードとサブノードの両方)のNSDictionaries、およびファイルシステム参照としてのNSURL。私はあなたの元のコードにできるだけ近づけるように努めました。結局、それは次のようになりました:

ProjectViewController.h

@interface ProjectViewController : NSViewController <NSOutlineViewDataSource, NSObject>
{
    IBOutlet NSOutlineView          *outlineView;
    NSURL                           *content;
}

@end

ProjectViewController.m

#import "ProjectViewController.h"

@interface ProjectViewController () {
    NSMutableArray* _objects;
}
@property (nonatomic, retain, readwrite) NSMutableArray* objects;
@end

@implementation ProjectViewController

@synthesize objects = _objects;

- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {
    if (self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]) {
        // Initialization code here.
        // Setting default path to the local file or directory
        NSString *home = NSHomeDirectory();
        content = [[NSURL alloc] initFileURLWithPath:home];

        [self defineContentNSOutlineView];
        NSLog(@"Array: %@",_objects);

        // Basic сonfiguration an instance NSOutlineView
        [self configurationNSOutlineView];
    }
    return self;
}

// nodes have 3 keys: title, url, icon
- (NSArray*)p_childrenForNode: (NSMutableDictionary*)node {
    if (nil == node)
        return self.objects;

    NSArray* retVal = nil;
    if (nil == (retVal = [node valueForKey: @"children"]))
    {
        NSMutableArray* children = [NSMutableArray array];
        for (NSURL* urlInDir in [[NSFileManager defaultManager] contentsOfDirectoryAtURL: [node objectForKey: @"url"]
                                                           includingPropertiesForKeys: [NSArray arrayWithObjects: NSURLNameKey, NSURLEffectiveIconKey, nil]
                                                                              options: 0
                                                                                error: NULL])
        {
            id name = [urlInDir getResourceValue: &name forKey: NSURLNameKey error: NULL] ? name : @"<Couldn't get name>";
            id icon = [urlInDir getResourceValue: &icon forKey: NSURLEffectiveIconKey error: NULL] ? icon : nil;

            NSMutableDictionary* dict = [NSMutableDictionary dictionaryWithObjectsAndKeys: urlInDir, @"url", name, @"title", nil];

            if (icon)
                [dict setObject: icon forKey: @"icon"];

            [children addObject: dict];
        }

        retVal = children;

        if (children)
            [node setValue: children forKey: @"children"];
    }
    return retVal;
}

- (id)outlineView:(NSOutlineView *)outlineView child:(NSInteger)index ofItem:(id)item {
    NSMutableDictionary* itemDict = (NSMutableDictionary*)item;
    NSArray* children = [self p_childrenForNode: itemDict];
    return children.count > index ? [[[children objectAtIndex: index] retain] autorelease] : nil;
}

- (BOOL)outlineView:(NSOutlineView *)outlineView isItemExpandable:(id)item {
    NSMutableDictionary* itemDict = (NSMutableDictionary*)item;
    NSArray* children = [self p_childrenForNode: itemDict];
    return children.count > 0;
}

- (NSInteger)outlineView:(NSOutlineView *)outlineView numberOfChildrenOfItem:(id)item {
    NSMutableDictionary* itemDict = (NSMutableDictionary*)item;
    NSArray* children = [self p_childrenForNode: itemDict];
    NSInteger retVal = children.count;
    return retVal;
}

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

    NSImage* icon = [item objectForKey: @"icon"];
    NSString* title = [item objectForKey: @"title"];
    id value = nil;

    if (icon) {
        [icon setSize: NSMakeSize(pOutlineView.rowHeight - 2, pOutlineView.rowHeight - 2)];
        NSTextAttachment* attachment = [[[NSTextAttachment alloc] init] autorelease];
        [(NSCell *)[attachment attachmentCell] setImage: icon];
        NSMutableAttributedString *aString = [[[NSAttributedString attributedStringWithAttachment:attachment] mutableCopy] autorelease];
        [[aString mutableString] appendFormat: @" %@", title];
        value = aString;
    } else {
        value = title;
    }

    return value;
}

- (void)defineContentNSOutlineView {
    // Make root object
    NSMutableDictionary* rootObj = [NSMutableDictionary dictionaryWithObjectsAndKeys:
                                    @"FINDER", @"title",
                                    content, @"url",
                                    nil];

    id icon = [content getResourceValue: &icon forKey: NSURLEffectiveIconKey error: NULL] ? icon : nil;
    if (icon)
        [rootObj setObject: icon forKey: @"icon"];

    // Set it
    self.objects = [NSMutableArray arrayWithObject: rootObj];
}

- (void)configurationNSOutlineView {
    [outlineView sizeLastColumnToFit];
    [outlineView setFloatsGroupRows:NO];
    [outlineView reloadData];
    [outlineView expandItem:nil expandChildren:YES];
}

@end

動作中のサンプルプロジェクト全体をGitHubに投稿しました。

于 2012-12-28T18:23:42.067 に答える