4

我想NSSplitView在我的NSSplitViewController.

文档说:

要提供自定义拆分视图,请在继承的 viewDidLoad() 方法中调用 super 之前随时设置此属性;也就是说,在拆分视图控制器的 isViewLoaded 属性为 true 之前。

我的NSSplitViewController子类称为MainVC.

我尝试-viewDidLoad在调用之前设置我的自定义拆分视图[super viewDidLoad]

- (void)viewDidLoad {
    self.splitView = [MySplitView new];
    [super viewDidLoad];
    // Rest of viewDidLoad...
}

但它没有用。我收到以下错误:

2017-09-02 10:35:43.527312-0700 Zee[6497:632581] ** * 断言失败 -[MainVC setSplitView:], /BuildRoot/Library/Caches/com.apple.xbs/Sources/AppKit/AppKit- 1561/控制器/NSSplitViewController.m:220

2017-09-02 10:35:43.527558-0700 Zee[6497:632581] MainVC:-splitView 只能在视图加载之前分配

我也尝试过覆盖loadView

- (void)loadView {
    self.splitView = [MySplitView new];
    [super loadView];
}

但我得到:

2017-09-02 10:39:39.377345-0700 Zee[6575:639146] ** * -[__NSArrayM objectAtIndex:]:空数组的索引 0 超出范围

如果我在调用后执行分配[super loadView],我会得到与我在中尝试时相同的错误-viewDidLoad

如何NSSplitView在我的NSSplitViewController子类中使用自定义?

4

4 回答 4

6

该线程中接受的答案在技术上是正确的,但是(可以理解)错过了一个NSSplitViewController我在任何地方都没有发现的错误。这就是 2017 年 Cocoa 的发展状况,我猜……

无论如何,问题是这样的:如果您像我一样想要使用仅以一个视图开头NSSplitViewController的an NSSplitView,则上面的子类化方法将不起作用,并且您将从 OP 获得索引错误。有一种私有方法(用于绘制分隔线)假设两个's 始终在其中,即使只有一个也可以正常工作。NSSplitViewItemNSSplitView

我最终做的是继承NSSplitViewControllerand NSSplitView,并检查我是否创建了一个只有一个视图的视图,并交换了一个空白NSViewController实例,一旦加载阶段稳定下来,该实例就会被删除。我还发现splitViewController.splitViewItems = ...直接设置效果不好,你应该打电话addSplitViewItem:来做这件事——大概有一些幕后的东西你会错过。

令人讨厌的是,这个类没有记录在案,尽管它总体上非常有用。如果你是一个任性的旅行者并且你发现了这个,希望它对你有所帮助。

于 2018-01-05T22:49:49.710 回答
3

因此,索引越界问题与您的拆分视图没有任何内容有关,而不是您在初始化时做错了什么。将初始化留在 loadView 中应该没问题。只需确保在呈现之前已使用至少 2 个 NSSplitViewItem 初始化 NSSplitViewController 子类。这是一个例子:

- (void)applicationDidFinishLaunching:(NSNotification *)aNotification {
    MySplitViewController *vc = [MySplitViewController new];
    vc.splitViewItems = @[
        [NSSplitViewItem splitViewItemWithViewController:[MyViewController new]],
        [NSSplitViewItem splitViewItemWithViewController:[MyViewController new]]
    ];
    self.window.contentViewController = vc;
}
于 2017-09-05T22:59:01.390 回答
1

就我而言,这行得通。(macOS 10.14、Xcode 10)

final class SplitVC: NSSplitViewController {
    private func patch() {
        let v = NSSplitView()
        v.isVertical = true
        v.dividerStyle = .thin
        splitView = v
        splitViewItems = [
            NSSplitViewItem(viewController: NSTabViewController()),
            NSSplitViewItem(viewController: NSTabViewController()),
        ]
    }

    override init(nibName nibNameOrNil: NSNib.Name?, bundle nibBundleOrNil: Bundle?) {
        super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil)
        patch()
    }
    required init?(coder: NSCoder) {
        super.init(coder: coder)
        patch()
    }
}
于 2018-10-07T11:17:52.703 回答
0

我偶然发现了我认为是这个问题的根源。它发生在splitView(_ splitView: NSSplitView, shouldHideDividerAt dividerIndex: Int) -> Bool. 我认为 Apple 在该方法中错误地索引会导致越界错误。

要跳过调用它们的实现,只需在您的NSSplitViewController子类中覆盖它:

  override func splitView(_ splitView: NSSplitView, shouldHideDividerAt dividerIndex: Int) -> Bool {
    false
  }

如果您改为调用super.shouldHideDividerAt(...)错误开始再次发生:

*** -[__NSArrayM objectAtIndex:]: index 1 beyond bounds [0 .. 0]

其他人提供的添加“虚拟” splitViewItems 的解决方案对我有用,直到我添加了一个覆盖insertSplitViewItem并查看了我的 NSSplitViewController 子类的.view.frameor .splitViewItems,然后越界错误又回来了,我又被卡住了。

在感到沮丧之后,我去了 GitHub 看看我是否能走运并找到解决这个错误的人。我遇到了这个评论/代码:https ://github.com/MoonfishDeFi/Composite/blob/1ccde807c690739b1739e22f02213e195265a992/cotEditor/Document%20Window/Document%20View/SplitViewController.swift#L62有这个解决方案但没有解释。

于 2022-01-29T20:40:58.393 回答