我被这一整天困扰,请帮助。我已经搜索过高低,无法解决这个问题。
我已经创建了一个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
答案 0 :(得分:1)
你不应该将NSOutlineView子类化为一个OutlineViewController类。
您的委托/数据源对象可以继承很多东西。但它不应该继承自NSView。使用MVC,你会遇到MC部分混在一起的情况,但如果你正在制作一个C,那么肯定不会将V子类化。
如果要在IB中实例化控制器对象,可以让您的类继承自NSObject,并将对象多维数据集拖到Nib中,并使其自定义类成为自定义类。但是你不一定需要IB中的控制器对象。
在OSX中,委托和数据源协议通常由Nib的文件所有者实现。所以,如果它是一个窗口笔尖,那将是一个NSWindowController。如果它是一个视图nib,它将是一个NSViewController。您可以将其中任何一个子类化,并将文件的所有者设置为自定义控制器类,然后在该类中实现协议,然后可以将IB中的outlineview数据源/委托连接拖到文件所有者,并且Nib加载过程将确保将outlineview连接到控制器方法实现。