在单个窗口界面中跨多个视图控制器绑定选择
我在思考如何跨两个视图控制器连接一些 NSArrayController 时遇到了一个问题。我想同步源列表表视图中的选择以更新第二个详细视图控制器中的值。
我使用 Cocoa Dev Central 构建核心数据教程 作为起点,但是分解了架构,以便有一个 NSWindowController 包含两个 NSViewController:一个用于左侧的帖子表,一个用于右侧的帖子详细信息。
NSWindowController 子类有一个绑定到 Post 实体的 NSArrayController 和一个指向 [[NSApp delegate] ManagedObjectContext]
的只读 ManagedObjectContext 访问器,
然后我在 windowDidLoad 中初始化两个视图控制器方法。
- (void)windowDidLoad
{
static NSInteger kSourceListViewIndex = 0;
static NSInteger kDetailViewIndex = 1;
self.postsListsViewController = [[MDVCPostsListViewController alloc] initWithWindowController:self];
NSView *sourceListSplitViewContentView = [[self.splitView subviews] objectAtIndex:kSourceListViewIndex];
NSView *sourceListView = [self.postsListsViewController view];
[sourceListView setFrame:[sourceListSplitViewContentView bounds]];
[sourceListView setAutoresizingMask:(NSViewWidthSizable | NSViewHeightSizable)];
[sourceListSplitViewContentView addSubview:sourceListView];
// And now let's load the detail view.
self.postDetailViewController = [[MDVCPostDetailViewController alloc] initWithWindowController:self];
NSView *detailSplitViewContentView = [[self.splitView subviews] objectAtIndex:kDetailViewIndex];
NSView *detailView = [self.postDetailViewController view];
[detailView setFrame:[detailSplitViewContentView bounds]];
[detailView setAutoresizingMask:(NSViewWidthSizable | NSViewHeightSizable)];
[detailSplitViewContentView addSubview:detailView];
}
MDVCPostsListViewController
有一个绑定到 Post 实体的 NSArrayController,其托管对象上下文绑定到父窗口控制器的托管对象上下文(全部通过 Interface Builder)
MDVCPostDetailViewController
有一个 NSObjectController 绑定到窗口控制器的托管对象上下文和通过 postsListsViewController.postsArrayController.selection 绑定到窗口控制器的内容对象。这似乎是一个非常糟糕的黑客行为。
如何获取它,以便更改 MDVCPostsListViewController
的表视图中的选择将更新 MDVCPostDetailViewController
中的选定值?我觉得我已经很接近了,但不确定缺少什么或最好的路线是什么。我确实觉得 postsListsViewController.postsArrayController.selection
绑定非常糟糕。希望有更好的方法。
我已经上传了我的示例项目,为那些喜欢查看代码而不仅仅是阅读描述的人展示了这一点。您可以从我的网站 http://www.secondgearsoftware.com/attachments/stackoverflow_objectcontroller. 获取它。邮编
I am having an issue wrapping my head around how to hook up a few NSArrayControllers across two view controllers. I want to sync the selection in the source list table view to update the values in the second detail view controller.
I'm using the Cocoa Dev Central Build A Core Data Tutorial as the starting point, but have broke down the architecture so that there is an NSWindowController that contains two NSViewControllers: one for the posts table on the left and one for the post details on the right.
The NSWindowController subclass has an NSArrayController that is bound to the Post entity and a read-only managedObjectContext accessor that points to [[NSApp delegate] managedObjectContext]
I then initializing the two view controllers in the windowDidLoad
method.
- (void)windowDidLoad
{
static NSInteger kSourceListViewIndex = 0;
static NSInteger kDetailViewIndex = 1;
self.postsListsViewController = [[MDVCPostsListViewController alloc] initWithWindowController:self];
NSView *sourceListSplitViewContentView = [[self.splitView subviews] objectAtIndex:kSourceListViewIndex];
NSView *sourceListView = [self.postsListsViewController view];
[sourceListView setFrame:[sourceListSplitViewContentView bounds]];
[sourceListView setAutoresizingMask:(NSViewWidthSizable | NSViewHeightSizable)];
[sourceListSplitViewContentView addSubview:sourceListView];
// And now let's load the detail view.
self.postDetailViewController = [[MDVCPostDetailViewController alloc] initWithWindowController:self];
NSView *detailSplitViewContentView = [[self.splitView subviews] objectAtIndex:kDetailViewIndex];
NSView *detailView = [self.postDetailViewController view];
[detailView setFrame:[detailSplitViewContentView bounds]];
[detailView setAutoresizingMask:(NSViewWidthSizable | NSViewHeightSizable)];
[detailSplitViewContentView addSubview:detailView];
}
MDVCPostsListViewController
has an NSArrayController bound to the Post entity and its managed object context bound to the parent window controller's managed object context (all through Interface Builder)
MDVCPostDetailViewController
has an NSObjectController bound to the window controller's managed object context and the content object bound to the window controller via postsListsViewController.postsArrayController.selection
. This seems like a really sucky hack.
How can I get it so that changing the selection in MDVCPostsListViewController
's table view will update the selected values in MDVCPostDetailViewController
? I feel like I'm close, but am not sure what's missing or what is the best route to take. I do feel that the postsListsViewController.postsArrayController.selection
binding is extremely hacky. Hopefully there's a better way.
I've uploaded my sample project that exhibits this for those that prefer to look at code rather than just read descriptions. You can grab it from my site at http://www.secondgearsoftware.com/attachments/stackoverflow_objectcontroller.zip
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
您期望每个窗口控制器如何发现主窗口控制器?
快速浏览一下该项目,您似乎只是向每个 NIB 添加了一个 MDVCMainWindowController 实例。这些将是与实际运行主窗口的实例不同的实例。
您需要将源列表选择索引绑定到 Post 数组控制器。否则,控制器级别将不知道该选择。
我建议将阵列控制器移至主窗口控制器中。在 windowDidLoad 方法中,您可以将其传递到列表和详细视图。列表将绑定到arrangedObjects 和selectionIndexes,详细信息视图将绑定到selection.someKey。
How do you expect each window controller to discover the main window controller?
From a quick glance at the project, it seems you just added an instance of MDVCMainWindowController to each NIB. These will be separate instances from the one actually running the main window.
You need to bind your source list table selectionIndexes to the the Post array controller. Otherwise the selection will not be known at the controller level.
I would suggest moving the array controller up into the main window controller. In your windowDidLoad method you could then pass it down to both the list and detail view. The list would bind to arrangedObjects and selectionIndexes, the detail view would bind to selection.someKey.
问题在于详细视图 xib 中 NSObjectController 实例的内容对象绑定。列表视图 xib 中的数组控制器正确发布 KVO 通知(通过让 MDVCPostDetailViewController 实例使用 KVO 观察这一点来检查这一点),所以我不确定为什么,但由于某种原因,对象控制器没有响应它们。
但是,您可以采取几种不同的有效方法。您可以摆脱对象控制器并将详细视图 xib 中的文本字段等直接绑定到数组控制器(文件的 Owner.windowController.postsListsViewController.postsArrayController.selection.whatever)。或者,您可以保留对象控制器并让详细视图控制器观察数组控制器的选择属性,并在选择更改时“手动”设置对象控制器的内容对象属性。
The problem is with the NSObjectController instance's content object binding in the detail view xib. Your array controller in the list view xib is correctly posting KVO notifications (checked this by making the MDVCPostDetailViewController instance observe this with KVO), so I'm not sure why, but for some reason the object controller isn't responding to them.
However, there are a couple of different approaches you can take that will work. You can get rid of the object controller and bind the text fields, etc, in the detail view xib directly to the array controller (File's Owner.windowController.postsListsViewController.postsArrayController.selection.whatever). Alternatively you can keep the object controller and have your detail view controller observe the selection property of the array controller and 'manually' set the object controller's content object property when the selection changes.