简体   繁体   中英

macOS Swift: How to bind NSDocument variable to custom NSView variable

I have a simple custom NSView with one variable:

class MyView: NSView {
  var color: NSColor!
}

In my NSDocument I have the same variable.

Currently I am using a NSViewController that receives messages from the document via the NSObjectProtocol when the variable changes. Which means I've set up notifications over the default NotificationCenter . Then the controller sets the color in my view over an IBOutlet .

That works quite well but leaves me with a lot of glue code.

I was thinking I could use a NSObjectController and bind it to the color in my document. And then bind my color from the view to the objectController.

Probably I got something wrong because I am having a hard time to access or even find the color variable in the view. It doesn't show up in the Interface Builder Storyboard.

I wonder how to prepare the variable in my view to be bindable?!

Since KVC and KVO are built on the Objective-C runtime, and since Cocoa Bindings is built on top of KVC and KVO, any properties you want to use Cocoa Bindings with need to be exposed to Objective-C. At the bare minimum, that means adding @objc to the declaration:

@objc var color: NSColor!

However, if the color property can be changed at runtime, there's an additional hurdle you need to jump through; you need to make sure that the KVO notifications will fire whenever the property's setter is called. Apple's implementation of KVO will use Objective-C magic to automatically add the needed notifications to the setter, but since Swift property accesses aren't guaranteed to go through the Objective-C runtime, you need to add the dynamic keyword for this to work reliably:

@objc dynamic var color: NSColor!

If color is a computed property that depends on something else, set up a keyPathsForValuesAffecting<Key> static property instead (exposed to Objective-C) to let KVO know of the dependency:

@objc dynamic var foo: NSColor!

@objc private static let keyPathsForValuesAffectingColor: Set<String> = [#keyPath(foo)]

@objc var color: NSColor! { return self.foo }

This will cause the notifications for color to be fired if foo changes.

Anyway, once your property is KVC-compliant, you should be able to bind things to it from Interface Builder.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM