I'd like to use a custom NSSplitView
with my NSSplitViewController
.
The docs say:
To provide a custom split view, set this property at any time before you call super in the inherited viewDidLoad() method; that is, before the split view controller’s isViewLoaded property is true.
My NSSplitViewController
subclass is called MainVC
.
I tried setting my custom split view in -viewDidLoad
before calling [super viewDidLoad]
:
- (void)viewDidLoad {
self.splitView = [MySplitView new];
[super viewDidLoad];
// Rest of viewDidLoad...
}
but it didn't work. I got the following error:
2017-09-02 10:35:43.527312-0700 Zee[6497:632581] ** * Assertion failure in -[MainVC setSplitView:], /BuildRoot/Library/Caches/com.apple.xbs/Sources/AppKit/AppKit- 1561/Controllers/NSSplitViewController.m:220
2017-09-02 10:35:43.527558-0700 Zee[6497:632581] MainVC: The -splitView can only be assigned before the view is loaded
I also tried overriding loadView
:
- (void)loadView {
self.splitView = [MySplitView new];
[super loadView];
}
But I get:
2017-09-02 10:39:39.377345-0700 Zee[6575:639146] ** * -[__NSArrayM objectAtIndex:]: index 0 beyond bounds for empty array
If I do the assignment after calling [super loadView]
, I get the same error as I did when I tried it in -viewDidLoad
.
How do I use a custom NSSplitView
in my NSSplitViewController
subclass?
The accepted answer in this thread is technically correct, but (understandably) misses a bug in NSSplitViewController
that I haven't found documented anywhere. Such is the state of Cocoa development in 2017, I guess...
Anyway, the issue is this: if you're like me and wanted to use an NSSplitViewController
with an NSSplitView
that starts with just one view, the subclassing approach above won't work and you'll get the indexing error from OP. There's a private method (for drawing the divider) that assumes two NSSplitViewItem
's are in there at all times, even though NSSplitView
works fine with just one.
What I ended up doing is subclassing both NSSplitViewController
and NSSplitView
, and providing a check for if I create one that only has one view and swapping in a blank NSViewController
instance that gets removed once the loading phase has settled down. I've also found that setting splitViewController.splitViewItems = ...
directly doesn't work well, and you should be calling through to addSplitViewItem:
to do this - presumably there's some stuff behind the scenes that you miss out on otherwise.
This class is annoyingly not documented, even though it's pretty useful overall. If you're a wayward traveler and you find this, hope it helps.
So the index out of bounds issue is related to your split view not having any content rather than something you're doing wrong with initialization. Leaving the initialization in the loadView should be fine. Simply make sure you have initialized your NSSplitViewController subclass with at least 2 NSSplitViewItems before presenting it. Here's an example:
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification {
MySplitViewController *vc = [MySplitViewController new];
vc.splitViewItems = @[
[NSSplitViewItem splitViewItemWithViewController:[MyViewController new]],
[NSSplitViewItem splitViewItemWithViewController:[MyViewController new]]
];
self.window.contentViewController = vc;
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With