NSSplitViewController/NSSplitViewItem XIB 中的支持
NSSplitViewController/NSSplitViewItem support in XIBs
XIB 是否支持 NSSplitViewController/NSSplitViewItem?我只看到 NSSplitView
我可以只拖放 NSViewController 并将其子类化为 NSSplitViewController 吗?我如何添加 NSSplitViewItem,它通常开箱即用?
我可以很容易地在情节提要中看到对它们的支持。
拆分视图控制器不是 xib 文件对象库的一部分。使用拆分视图控制器的最简单方法是使用故事板。
如果您不愿意使用故事板,最好的选择是创建 NSSplitViewController 的子class 和 select 复选框以同时创建一个 xib 文件。
将拆分视图添加到拆分视图控制器 xib 文件。编写代码加载 xib 文件以设置拆分视图控制器。
更新
查看 NSNib class 参考以获取有关加载 xib 文件的信息。 xib 文件的文件所有者是您的 NSSplitViewController subclass。您可以使用该信息来设置拆分视图控制器。最坏的情况是你必须编写代码从 xib 文件加载拆分视图,将拆分视图控制器的拆分视图设置为你加载的拆分视图,并将拆分视图项添加到拆分视图控制器。有关详细信息,请参阅 NSSplitViewController class 参考。
是的,这是可能的。但它需要一些布线。
首先添加 NSSplitViewItem
的自定义子 class 并将 viewController
属性 公开为 IBOutlet。编译器会发出警告,所以不要忘记将 属性 标记为动态。
@interface MySplitViewItem : NSSplitViewItem
@property IBOutlet NSViewController *viewController;
@end
@implementation MySplitViewItem
@dynamic viewController;
@end
在您的 XIB 中添加 3 个 NSViewController 对象。其中之一更改为自定义 class NSSplitViewController。重要的是要注意不要添加 NSSplitView
。将 NSViewControllers
连接到它的 views
。还添加 2 个对象并添加 MySplitViewItem
的自定义 class,它已暴露 viewController
并连接它。
最后一步。在加载视图之前设置 属性 splitItems
of NSSplitViewController
很重要!否则你会被 NSAssert 宏捕获。
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
NSNib *nib = [[NSNib alloc] initWithNibNamed:@"Empty" bundle:nil];
NSMutableArray *test = [NSMutableArray new];
NSMutableArray *splitItems = [NSMutableArray new];
NSSplitViewController *controller;
[nib instantiateWithOwner:self topLevelObjects:&test];
for (id object in test) {
if ([object isKindOfClass:[NSSplitViewController class]]) {
controller = object;
}
if ([object isKindOfClass:[NSSplitViewItem class]]) {
[splitItems addObject:object];
}
}
[controller setValue:splitItems forKey:@"splitViewItems"];
[[self window] setContentViewController:controller];
}
这是一个证明一切都正确连接的证据。请注意,我没有接触 XIB 中的委托,它是有线的。魔术,我知道。
PS:必须将 XIB 设置为更喜欢 Coder + 自动布局。
为什么我更喜欢 XIB?因为我们可以创建更大的 XIB,它不会受到数据隔离的影响(可以轻松地跨 NSViewControllers 进行绑定)。
我还尝试在 viewDidLoad
或 setView
或 awakeFromNib
中添加 splitViewItems
:在 NSSplitViewController
的自定义子 class 中(具有公开的 NSSplitViewItem 属性)。如果有人在这里找到解决方案,将不胜感激。
只需要代码的解决方案:
- (NSSplitViewController *)profilesSVC
{
if (!_profilesSVC) {
NSSplitViewController *splitVC = [[NSSplitViewController alloc] init];
ProfilesViewController *profilesVC = [[ProfilesViewController alloc] initWithNibName:@"Profiles" bundle:nil];
NSSplitViewItem *leftItem = [NSSplitViewItem splitViewItemWithViewController:profilesVC];
[splitVC addSplitViewItem:leftItem];
ProfileViewController *profileVC = [[ProfileViewController alloc] initWithNibName:@"Profile" bundle:nil];
NSSplitViewItem *rightItem = [NSSplitViewItem splitViewItemWithViewController:profileVC];
[splitVC addSplitViewItem:rightItem];
_profilesSVC = splitVC;
}
return _profilesSVC;
}
我也想在我的不使用故事板的项目(macOS 应用程序)中添加一个 splitView 控制器。
事实证明,这很容易(在 XCode 12.4 中)。
按照建议,必须将 NSViewController
个对象添加到 xib 并将每个 view
属性 连接到相应的 'pane' (拆分视图的子视图)在界面生成器中。
然后创建NSSplitViewController
的子class(不需要创建xib文件)。
将第三个 NSViewController
对象添加到 xib 并将其 class 更改为您的子对象class。然后将 both 它的 view
和 splitView
属性连接到您的 splitView。如果你只是连接 splitView
属性.
它不会加载任何视图
可能不需要使用 NSSplitViewController
的子class,但它很方便,因为您可以在 viewDidLoad
中设置 splitViewItems(如下)。由于此对象(自动)是 splitView 的委托,因此您也可以根据需要覆盖委托方法。
该对象应该有通向您之前连接到 IB 窗格的 NSViewController
对象的出口。
我设置了两个名为 leftController
和 rightController
的插座。
我的 awakeFromNib
方法如下所示(抱歉,我不使用 swift):
- (void) viewDidLoad {
self.splitView.wantsLayer = YES; // I think this is required if you use a left sidebar with vibrancy (which I do below). Otherwise appkit complains and forces the use of CA layers anyway
NSSplitViewItem *left =[NSSplitViewItem sidebarWithViewController:leftController];
[self addSplitViewItem:left];
NSSplitViewItem *right =[NSSplitViewItem splitViewItemWithViewController:rightController];
right.minimumThickness = 420;
[self addSplitViewItem:right];
}
瞧!
但是,如果我在 IB 中设置厚分隔线,因为 appkit 调用 splitView:shouldHideDividerAtIndex
过早,此时显然还没有分隔线,我会崩溃。更糟糕的是,它可能会传递负分频器索引 (!!)。但是您可以覆盖该方法并采取相应的行动,我对细分隔线没有问题。
XIB 是否支持 NSSplitViewController/NSSplitViewItem?我只看到 NSSplitView
我可以只拖放 NSViewController 并将其子类化为 NSSplitViewController 吗?我如何添加 NSSplitViewItem,它通常开箱即用?
我可以很容易地在情节提要中看到对它们的支持。
拆分视图控制器不是 xib 文件对象库的一部分。使用拆分视图控制器的最简单方法是使用故事板。
如果您不愿意使用故事板,最好的选择是创建 NSSplitViewController 的子class 和 select 复选框以同时创建一个 xib 文件。
将拆分视图添加到拆分视图控制器 xib 文件。编写代码加载 xib 文件以设置拆分视图控制器。
更新
查看 NSNib class 参考以获取有关加载 xib 文件的信息。 xib 文件的文件所有者是您的 NSSplitViewController subclass。您可以使用该信息来设置拆分视图控制器。最坏的情况是你必须编写代码从 xib 文件加载拆分视图,将拆分视图控制器的拆分视图设置为你加载的拆分视图,并将拆分视图项添加到拆分视图控制器。有关详细信息,请参阅 NSSplitViewController class 参考。
是的,这是可能的。但它需要一些布线。
首先添加 NSSplitViewItem
的自定义子 class 并将 viewController
属性 公开为 IBOutlet。编译器会发出警告,所以不要忘记将 属性 标记为动态。
@interface MySplitViewItem : NSSplitViewItem
@property IBOutlet NSViewController *viewController;
@end
@implementation MySplitViewItem
@dynamic viewController;
@end
在您的 XIB 中添加 3 个 NSViewController 对象。其中之一更改为自定义 class NSSplitViewController。重要的是要注意不要添加 NSSplitView
。将 NSViewControllers
连接到它的 views
。还添加 2 个对象并添加 MySplitViewItem
的自定义 class,它已暴露 viewController
并连接它。
最后一步。在加载视图之前设置 属性 splitItems
of NSSplitViewController
很重要!否则你会被 NSAssert 宏捕获。
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
NSNib *nib = [[NSNib alloc] initWithNibNamed:@"Empty" bundle:nil];
NSMutableArray *test = [NSMutableArray new];
NSMutableArray *splitItems = [NSMutableArray new];
NSSplitViewController *controller;
[nib instantiateWithOwner:self topLevelObjects:&test];
for (id object in test) {
if ([object isKindOfClass:[NSSplitViewController class]]) {
controller = object;
}
if ([object isKindOfClass:[NSSplitViewItem class]]) {
[splitItems addObject:object];
}
}
[controller setValue:splitItems forKey:@"splitViewItems"];
[[self window] setContentViewController:controller];
}
这是一个证明一切都正确连接的证据。请注意,我没有接触 XIB 中的委托,它是有线的。魔术,我知道。
PS:必须将 XIB 设置为更喜欢 Coder + 自动布局。
为什么我更喜欢 XIB?因为我们可以创建更大的 XIB,它不会受到数据隔离的影响(可以轻松地跨 NSViewControllers 进行绑定)。
我还尝试在 viewDidLoad
或 setView
或 awakeFromNib
中添加 splitViewItems
:在 NSSplitViewController
的自定义子 class 中(具有公开的 NSSplitViewItem 属性)。如果有人在这里找到解决方案,将不胜感激。
只需要代码的解决方案:
- (NSSplitViewController *)profilesSVC
{
if (!_profilesSVC) {
NSSplitViewController *splitVC = [[NSSplitViewController alloc] init];
ProfilesViewController *profilesVC = [[ProfilesViewController alloc] initWithNibName:@"Profiles" bundle:nil];
NSSplitViewItem *leftItem = [NSSplitViewItem splitViewItemWithViewController:profilesVC];
[splitVC addSplitViewItem:leftItem];
ProfileViewController *profileVC = [[ProfileViewController alloc] initWithNibName:@"Profile" bundle:nil];
NSSplitViewItem *rightItem = [NSSplitViewItem splitViewItemWithViewController:profileVC];
[splitVC addSplitViewItem:rightItem];
_profilesSVC = splitVC;
}
return _profilesSVC;
}
我也想在我的不使用故事板的项目(macOS 应用程序)中添加一个 splitView 控制器。
事实证明,这很容易(在 XCode 12.4 中)。
按照建议,必须将 NSViewController
个对象添加到 xib 并将每个 view
属性 连接到相应的 'pane' (拆分视图的子视图)在界面生成器中。
然后创建NSSplitViewController
的子class(不需要创建xib文件)。
将第三个 NSViewController
对象添加到 xib 并将其 class 更改为您的子对象class。然后将 both 它的 view
和 splitView
属性连接到您的 splitView。如果你只是连接 splitView
属性.
可能不需要使用 NSSplitViewController
的子class,但它很方便,因为您可以在 viewDidLoad
中设置 splitViewItems(如下)。由于此对象(自动)是 splitView 的委托,因此您也可以根据需要覆盖委托方法。
该对象应该有通向您之前连接到 IB 窗格的 NSViewController
对象的出口。
我设置了两个名为 leftController
和 rightController
的插座。
我的 awakeFromNib
方法如下所示(抱歉,我不使用 swift):
- (void) viewDidLoad {
self.splitView.wantsLayer = YES; // I think this is required if you use a left sidebar with vibrancy (which I do below). Otherwise appkit complains and forces the use of CA layers anyway
NSSplitViewItem *left =[NSSplitViewItem sidebarWithViewController:leftController];
[self addSplitViewItem:left];
NSSplitViewItem *right =[NSSplitViewItem splitViewItemWithViewController:rightController];
right.minimumThickness = 420;
[self addSplitViewItem:right];
}
瞧!
但是,如果我在 IB 中设置厚分隔线,因为 appkit 调用 splitView:shouldHideDividerAtIndex
过早,此时显然还没有分隔线,我会崩溃。更糟糕的是,它可能会传递负分频器索引 (!!)。但是您可以覆盖该方法并采取相应的行动,我对细分隔线没有问题。