Поддержка NSSplitViewController/NSSplitViewItem в XIB

Есть ли поддержка NSSplitViewController/NSSplitViewItem для XIB? Я вижу только NSSplitView

Могу ли я просто перетащить NSViewController и сделать его подклассом NSSplitViewController? Как добавить NSSplitViewItem, чтобы он работал в основном из коробки?

Я легко вижу их поддержку в раскадровке.

3 ответа

Да, это возможно. Но для этого нужна проводка.

Сначала добавьте пользовательский подкласс NSSplitViewItem и разоблачить viewController собственность как IBOutlet. Компилятор выдаст предупреждение, поэтому не забудьте пометить свойство как динамическое.

@interface MySplitViewItem : NSSplitViewItem
@property  IBOutlet NSViewController *viewController;
@end

@implementation MySplitViewItem
@dynamic viewController;
@end

В вашей XIB добавьте 3 объекта NSViewController. Один из них меняется на пользовательский класс NSSplitViewController. Важно отметить, что не следует добавлять NSSplitView, провод NSViewControllers к этому views, Также добавьте 2 объекта и добавьте пользовательский класс MySplitViewItem который разоблачил viewController и подключите его.

Последний шаг. Важно установить свойство splitItems из 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 должен быть установлен, чтобы предпочесть кодер + автоматическое расположение.

Почему я предпочитаю XIB? Потому что мы можем создать более крупный XIB, который не страдает от изоляции данных (легко может делать привязки через NSViewControllers).

Я также экспериментировал, чтобы добавить splitViewItems в viewDidLoad или же setView или же awakeFromNib: в пользовательском подклассе NSSplitViewController (с открытыми свойствами 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;
}

Контроллер разделенного представления не является частью библиотеки объектов для файлов XIB. Самый простой способ использовать контроллеры с разделенным видом - это использовать раскадровки.

Если вы не хотите использовать раскадровки, лучше всего создать подкласс NSSplitViewController и установить флажок, чтобы также создать файл xib.

Добавьте разделенное представление в xib-файл контроллера разделенного представления. Напишите код для загрузки xib-файла для настройки контроллера разделения представления.

ОБНОВИТЬ

Посмотрите на ссылку класса NSNib для информации о загрузке файла XIB. Владельцем файла xib-файла является ваш подкласс NSSplitViewController. Возможно, вы сможете использовать эту информацию для установки контроллера разделенного представления. В худшем случае вам нужно написать код для загрузки разделенного представления из xib-файла, установить разделенное представление контроллера разделенного представления на загруженное разделенное представление и добавить элементы разделенного представления в контроллер разделенного представления. См. Ссылку на класс NSSplitViewController для получения дополнительной информации.

Я тоже хотел добавить контроллер splitView в свой проект (приложение macOS), который не использует раскадровки.

Как оказалось, это было довольно просто (в XCode 12.4).

Как было предложено, нужно добавить объекты в xib и связать каждое свойство с соответствующей «панелью» (подвид разделенного представления) в построителе интерфейса.

Затем создайте подкласс (не нужно создавать файл xib).

Добавьте третий объект в xib и измените его класс на свой подкласс. Затем проволока оба это viewи свойства вашего splitView. Он не загружает никакого представления, если вы просто подключаете splitViewимущество.

Использование подкласса NSSplitViewControllerможет не требоваться, но это удобно, так как вы можете установить splitViewItems внутри viewDidLoad(ниже). Поскольку этот объект (автоматически) является делегатом splitView, вы также можете переопределить методы делегата, если хотите.

Этот объект должен иметь выходы, ведущие к NSViewControllerобъекты, которые вы ранее подключили к панелям в IB. Я установил две розетки с именем 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слишком рано, когда делителя видимо еще нет. Хуже того, он может передать отрицательный индекс делителя (!!). Но вы можете переопределить метод и действовать соответствующим образом, и у меня нет проблем с тонкими разделителями.

Другие вопросы по тегам