NSTableView与故事板中的NSArrayController绑定

时间:2015-03-22 20:04:42

标签: binding storyboard nstableview nsarraycontroller

我有一个用Objective-C编写的小型OS X测试项目,使用带有XCode 6.2的故事板,其目的是测试NSArray与基于视图的NSTableView的绑定。虽然这个区域在网上被打死了,但我不能出于某种原因使我有约束力的工作。

我已经定义了一个简单的对象TESTPerson,它已经从NSObject分类如下:

//  TESTPerson.h
//  TBLViewBindingTest

#import <Foundation/Foundation.h>

@interface TESTPerson : NSObject

@property (nonatomic,strong) NSString *strFirstName;
@property (nonatomic,strong) NSString *strLastName;

@end


#import "TESTPerson.h"

@implementation TESTPerson

-(instancetype)init
{
  if(!self)
  {
    self = [super init];
  }
  _strFirstName = @"First Name Test";
  _strLastName = @"Last Name Test";
  return self;
}
@end

我将NSTableView放入Storyboard提供的视图中,然后将NSArrayController放入View Controller场景中。

我在ViewController.h中为NSTableView和NSArrayController实例创建并附加IBOutlets。 NSArray * arrayNames也被声明,并将被NSArrayController用作内容源。

//  ViewController.h
//  TBLViewBindingTest

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

@interface ViewController : NSViewController

@property (strong) IBOutlet NSTableView *myTableView;
@property (nonatomic,strong) NSArray *arrayNames;
@property (strong) IBOutlet NSArrayController *myArrayController;

@end 


更新ViewController.m中的viewDidLoad以创建两个TESTPerson实例,然后将其添加到_arrayNames属性中。

//  ViewController.m
//  TBLViewBindingTest

#import "ViewController.h"

@implementation ViewController

- (void)viewDidLoad
{
  [super viewDidLoad];
  TESTPerson *p = [[TESTPerson alloc]init];
  TESTPerson *p1 = [[TESTPerson alloc]init];
  _arrayNames = [[NSArray alloc]initWithObjects:p,p1, nil];
}

- (void)setRepresentedObject:(id)representedObject
{
  [super setRepresentedObject:representedObject];
}
@end


我在Storyboard中选择了ArrayController,并在Attributes选项卡中将Class Name设置为&#39; TESTPerson&#39;,并设置Bindings选项卡以使用arrayNames的Model Key Path将ArrayController与我的ViewController绑定。我希望arrayNames将使用ViewController viewDidLoad方法中创建的两个TESTPerson实例进行填充。

然后,我在Storyboard中选择了Table View,并使用arrangeObjects的Controller Key将其Table Content设置为绑定到Array Controller。


向下钻取到TableView层次结构中,我为每列选择了“表视图单元”节点,并将值与表单元格视图绑定到对应的objectValue.strFirstName和objectValue.strLastName。

我的理解是,这是在tableview中显示我的数组中的数据所需的全部内容。但是,当我执行程序时,不会显示任何表格行。我通过NSLog添加了一个按钮/方法转储了ArrayController内容:

NSLog(@"%@",[_myArrayController content]);

告诉我_myArrayController没有任何内容:

`2015-03-22 13:48:49.379 TBLViewBindingTest[48776:4766635] (
)`

我仔细检查了View Controller Scene中的NSArrayController绑定到IBOutlet _myArrayController(它是)。

然后我在viewDidLoad中添加了一行代码,看看我是否可以强制进入_myArrayController:

[_myArrayController addObjects:_arrayNames];
NSLog(@"%@",[_myArrayController content]);

导致屏幕上填充的tableView和_myArrayController中的对象:

2015-03-22 13:50:28.240 TBLViewBindingTest[48807:4768827] (
    "<TESTPerson: 0x610000024ec0>",
    "<TESTPerson: 0x610000024ee0>",
    "<TESTPerson: 0x610000024ec0>",
    "<TESTPerson: 0x610000024ee0>"
)

对我来说,似乎不接受ArrayController实例和_arrayNames之间的绑定。我尝试了很多东西 - 在ArrayController属性选项卡中添加TESTPerson属性作为键,但无济于事。使用NSObject作为TESTPerson的基础应该足以使TESTPerson类符合KVC(?),但我想知道ArrayController是否不同意?

据我所知,基本数据显示所需的一切都在那里。我错过了什么?

1 个答案:

答案 0 :(得分:2)

问题是在-viewDidLoad中设置_arrayNames的内容对于NSArrayController和targetViewController的Controller Content之间的绑定执行来说太迟了。 (-viewWillAppear也太迟了)

怎么办?要解决此问题的示例代码中的问题,您可以为viewcontroller创建一个新的指定初始化程序,并在那里设置数组内容。

OS X 10.10中的Segues是另一种动物。在segue中调用的NSViewController的指定初始化程序似乎是-initWithCoder。如果覆盖-initWithCoder并从覆盖中调用[super initWithCoder:],您将在目标viewController中看到self.representedObject == nil。

通常我会将NSDictionary作为代表对象传递。

因此。填充已在viewController上定义为属性的源数组,用于在任何-viewWill ***中的NSArrayController和viewController的Controller内容之间的绑定(与模型键路径绑定到myViewController == self.myArray)方法为时已晚。

self.representedObject在segue中的目标viewController的指定初始值设定项中为nil,这意味着你无法在那里填充self.myArray。

对于踢,我直接在self.representedObject中传递一个NSArray,用于segue中的目标viewController。然后我调整了NSArrayController和targetViewController之间的Controller Content绑定,因此Model Key Path是self.representedObject。如果你这样做,绑定工作。