NSOutlineView不显示数据源中的数据

时间:2014-05-01 21:47:07

标签: objective-c xcode nstableview viewcontroller nsoutlineview

我被这一整天困扰,请帮助。我已经搜索过高低,无法解决这个问题。

我已经创建了一个OutlineViewController,我想处理我的大纲视图任务和数据源。如果我使用appDelegate作为我的数据源并将其连接到界面构建器中的OutlineView,我能够正常工作。但是,在将数据源以编程方式设置为自身(或以编程方式为appdelegate设置)时,我似乎无法使其工作。这是否被某种方式压倒了?

奇怪的是我注意到了。在调试时,通过接口构建器将appdelegate作为数据源连接,mainOutlineView属性将其数据源列为空。当我以编程方式设置它时会显示其链接,但不起作用。

请提出任何建议或示例!

OutlineViewController.h

#import <Cocoa/Cocoa.h>

@interface OutlineViewController : NSOutlineView <NSOutlineViewDataSource, NSOutlineViewDelegate>
{
    NSMutableDictionary *firstParent;
    NSMutableDictionary *secondParent;
    NSArray *list;
}

@end

OutlineViewController.m

#import "OutlineViewController.h"

static NSUserDefaults *ud1 = nil;

@implementation OutlineViewController

#pragma mark Initialization

- (id)init
{
    ud1 = [NSUserDefaults standardUserDefaults];
    if (self = [super init]) {
        // use ud if you want to initialize via init
        // ud = [NSUserDefaults standardUserDefaults];
        firstParent = [[NSMutableDictionary alloc] initWithObjectsAndKeys:@"James",@"parent",[NSArray arrayWithObjects:@"Mary",@"Charlie", nil],@"children", nil];

        secondParent = [[NSMutableDictionary alloc] initWithObjectsAndKeys:@"Elisabeth",@"parent",[NSArray arrayWithObjects:@"Jimmie",@"Kate", nil],@"children", nil];

        list = [NSArray arrayWithObjects:firstParent,secondParent, nil];
        [self setDataSource:self];
        [self setDelegate:self];

        NSLog(@"init OutlineViewController");
    }
    return self;
}

#pragma mark NSOutlineView Data Source Methods

- (BOOL)outlineView:(NSOutlineView *)outlineView isItemExpandable:(id)item
{
    if ([item isKindOfClass:[NSDictionary class]] || [item isKindOfClass:[NSArray 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:@"%li kids",[[item objectForKey:@"children"] count]];

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

    return nil;
}

- (BOOL)outlineView:(NSOutlineView *)outlineView shouldExpandItem:(id)item
{    
    return YES;
}

- (BOOL)outlineView:(NSOutlineView *)outlineView shouldCollapseItem:(id)item
{
    return YES;
}

- (void)dealloc
{
    NSLog(@"deallocating %@", self);
}

@end

AppDelegate.h

#import <Cocoa/Cocoa.h>
#import "OutlineViewController.h"

@interface AppDelegate : NSObject <NSApplicationDelegate>
{
    id<NSOutlineViewDataSource> oldDataSource;
    id<NSOutlineViewDelegate> oldDelegate;
}

@property (assign) IBOutlet NSWindow *window;
@property (weak) IBOutlet NSTextField *singerName;
@property (nonatomic) IBOutlet OutlineViewController *mainOutlineView;

- (IBAction)addSinger:(id)sender;

@end

AppDelegate.m

#import "AppDelegate.h"

@implementation AppDelegate

- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
    NSLog(@"appDidFinishLaunching");
    //_mainOutlineView = self.mainOutlineView.init;
}

- (void)awakeFromNib
{
    NSLog(@"awakeFromNib");
    self.mainOutlineView = [[OutlineViewController alloc] init];    

    [_mainOutlineView reloadData];
}

- (IBAction)addSinger:(id)sender
{
    NSLog(@"Add Singer Clicked %@", self.singerName.stringValue);

    //NSMutableArray *tempArray = [[NSMutableArray alloc] init];
    //tempArray = [[firstParent valueForKey:@"children"] mutableCopy];

    //[tempArray addObject:self.singerName.stringValue];
    //[firstParent setObject:tempArray forKey:@"children"];

    self.singerName.stringValue = @"";
    [self.mainOutlineView reloadData];
}
@end

1 个答案:

答案 0 :(得分:1)

你不应该将NSOutlineView子类化为一个OutlineViewController类。

您的委托/数据源对象可以继承很多东西。但它不应该继承自NSView。使用MVC,你会遇到MC部分混在一起的情况,但如果你正在制作一个C,那么肯定不会将V子类化。

如果要在IB中实例化控制器对象,可以让您的类继承自NSObject,并将对象多维数据集拖到Nib中,并使其自定义类成为自定义类。但是你不一定需要IB中的控制器对象。

在OSX中,委托和数据源协议通常由Nib的文件所有者实现。所以,如果它是一个窗口笔尖,那将是一个NSWindowController。如果它是一个视图nib,它将是一个NSViewController。您可以将其中任何一个子类化,并将文件的所有者设置为自定义控制器类,然后在该类中实现协议,然后可以将IB中的outlineview数据源/委托连接拖到文件所有者,并且Nib加载过程将确保将outlineview连接到控制器方法实现。

相关问题