我有一个用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
// 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是否不同意?
据我所知,基本数据显示所需的一切都在那里。我错过了什么?
答案 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。如果你这样做,绑定工作。