Cocoa 绑定到 NSToolbarItem 的连接是否会阻止取消初始化?

Does Cocoa connection binding to NSToolbarItem prevent deinitializing?

正在尝试通过连接绑定到 属性(optionSegment)来设置 NSToolbarItem 的选定段,即 NSSegmentedControl。继承 window 控制器

class MyWindow: NSWindowController {
    dynamic var optionSegment: Int = 0

    override func windowDidLoad() {
        super.windowDidLoad()
    }
}

或者,将 optionSegment 属性 放在 NSDocument 子类中并绑定到它。每项工作。问题是,使用此绑定,或看似对我的对象(视图、视图控制器、文档等)的 NSToolbarItem、none 的任何绑定都将取消初始化。有了绑定,他们就不会。删除绑定,他们就会这样做。

知道为什么会这样吗?建议?好难过。

谢谢!

正如 Willeke 所建议的,toolbarItem.view 是通往成功的道路。不得不说对象的层次结构对我来说并不总是很清楚,但是 .view 似乎是唯一的可能性,因为我一夜之间查看了 toolbarItem 挂钩,Willeke 的建议证实了这一点。有关绑定的 Apple 文档确实提到我们有责任解除某些对象的绑定,同时解除其他对象的绑定。这是我放入 NSDocument 子类中的代码,用于取消绑定所有内容,视图控制器现在正在取消初始化。

func windowWillClose(notification: NSNotification) {
    let wcs = self.windowControllers
    if wcs.count == 0 { return }
    let wc = wcs[0]
    let toolbar = wc.window?.toolbar
    if toolbar != nil {
        let items = toolbar!.items
        for item in items {
            let v = item.view
            if v != nil {
                // print(v?.className)
                let objects = v!.exposedBindings
                for object in objects {
                    // print(object + " " + item.label + " " + v!.className)
                    v!.unbind(object)
                }
            }
        }
    }
}

这是我 运行 遇到的最令人困惑的概念之一——太多的活动部分——感谢 Willeke 和 stevesliva 的对话,最终找到了解决方案。

来自 NSObject(NSKeyValueBindingCreation):

All standard bindings on AppKit objects (views, cells, table columns, controllers) unbind their bindings automatically when they are deallocated, but if you create key-value bindings for other kind of objects, you need to make sure that you remove those bindings before deallocation (observed objects have weak references to their observers, so controllers/model objects might continue referencing and messaging the objects that were bound to them).

我的 window 控制器由于绑定到其自定义属性而未取消初始化。在我的例子中,不仅 window 的工具栏视图需要解除绑定,触摸栏视图也需要解除绑定。感谢大家对这个问题的发现和建议!我正在分享我的片段。

WindowController 实例是 window 的委托。为简洁起见,NSView 和 NSTouchBar 的扩展。

extension WindowController: NSWindowDelegate {

    func windowWillClose(_ notification: Notification) {
        window?.toolbar?.items.forEach { [=10=].view?.unbindExposed() }
        if #available(macOS 10.12.2, *) {
            touchBar?.items.forEach { [=10=].view?.unbindExposed() }
        }
    }

}
extension NSView {

    /// Removes exposed binding between the receiver and a controller.
    func unbindExposed() {
        for binding in exposedBindings {
            unbind(binding)
        }
    }

}
@available(macOS 10.12.2, *)
extension NSTouchBar {

    /// The read-only list of items for the bar, as currently configured by the user.
    var items: [NSTouchBarItem] {
        itemIdentifiers.compactMap { item(forIdentifier: [=12=]) }
    }

}