views:

197

answers:

2

I'm just getting started with Cocoa Bindings and while I've read through much of the documentation, I'm still struggling to implement a basic feature, making me question wether I'm doing it wrong or perhaps it's just not possible via IB.

Goal: Have a menu item called "Toggle visibility" toggle the state of a Boolean property in my application controller (AppController) called "visibility." I think this should be possible completely through IB.

(Note: CoreData is not in use here)

What I think needs to happen is I need to have an NSObjectController who's content outlet is set to my AppController class. Then I think I need to use an Action Innvocation binding. But here's where I run into trouble.

Should the Controller Key be selection? Should the Model Key Path be the name of my Boolean Property? What should Selector Name be?

Or do I need to setup a separate action method called "toggleVisibility" that I can bind to? If I did, why wouldn't I just use standard target/action associations, rather than bindings?

Any input / direction appreciated.

A: 

If you have an instance of your App Delegate, you don't need the NSObjectController.
You can directly bind to the App Delegate's property.
To toggle your property, you can bind

Action Innvocation Argument:

  • Bind to: App delegate
  • Model Key Path: yourBool
  • Value Transformer: NSNegateBoolean (To toggle your bool)

Target:

  • Bind to: App delegate
  • Model Key Path: self
  • Selector Name: setYourBool: (don't forget the ':' in the selector)

One problem I ran into:
The approach described above does not work with plain BOOL data types.
I had to define yourBool as NSNumber. (I always thought the wrapping and unwrapping happens automatically.)

weichsel
That's not binding the menu item to a Boolean property; that's treating the setter as an action method and binding the menu item's target and action properties to make it send that “action” message. Since it's an action message, the menu item will pass *itself* as the first argument (`sender`), not an NSNumber. What you're doing is equivalent to declaring `setYourBool:` as an `IBAction` and hooking it up the more direct ctrl-drag way; it's just more work. Either way is wrong, though, if the goal is a solution that truly binds a property of the menu item to a Boolean property of the controller.
Peter Hosey
Thanks for the correction. Your answer is easier and HIG conform.
weichsel
+3  A: 

Goal: Have a menu item called "Toggle visibility" toggle the state of a Boolean property in my application controller (AppController) called "visibility."

Your goal tells you why you are failing.

In your description of your goal, you say that you want to set this menu item up as a command, a verb, an imperative sentence—“toggle the visibility”. But that's not the right title for the menu item.

Moreover, implementing a verb menu item with Bindings is inherently difficult because Bindings is the wrong tool for the job. Bindings is for exposing properties in your UI. It isn't for performing commands.

The correct title is supported by the correct Bindings-based solution.

The correct title of the menu item is, simply, “Visible”.

This alone should give you a hint as to how to proceed. Here's another: When the selection is visible, the menu item should have a check mark; when it is not visible, the menu item should have no mark.

You want to bind a property of the menu item to, ultimately, a Boolean property of your controller. Normally, this property of the menu item would be state, but for whatever reason, the binding for it is named value.

So, bind the value binding of the menu item to the Boolean property of your controller.

Peter Hosey
Appreciate the comments - those were not actually the names of the items - I was just trying to use generic names so as not confuse the issue. Apparently I failed. :)
Wade Williams
OK, so ignore my critique of your choice of menu item name. The solution remains the same: Bind the menu item's `value` to your controller's Boolean property.
Peter Hosey