Reputation: 4347
I am having some issues binding an NSMenuItem's "value" binding to a BOOL.
I simplified the problem to this:
1) The menu item must call the action method that changes the value of the BOOL otherwise it doesn't work (i.e. if an NSButton calls a method that changes the value of the BOOL then the menu item won't update)
2) Even if the action method makes the BOOL a constant (i.e. enabled = YES
), the "value" of the menu item still alternates.
Any ideas? I'm so confused!
Here is the code:
MenuBindings_AppDelegate.h
#import <Cocoa/Cocoa.h>
@interface Menu_BindingsAppDelegate : NSObject <NSApplicationDelegate>
{
BOOL foo;
}
- (IBAction)toggle:(id)sender;
- (IBAction)makeYes:(id)sender;
@property BOOL foo;
@end
Menu_BindingsAppDelegate.m
@implementation Menu_BindingsAppDelegate
@synthesize foo;
- (IBAction)toggle:(id)sender
{
[self setFoo:!foo];
}
- (IBAction)makeYes:(id)sender
{
[self setFoo:YES];
}
@end
In my nib, I have a button connected to the -makeYes: action and a menu item connected to the -toggle: action. The menu item's "value" binding is bound to the app delegate's "foo" attribute.
Thanks.
Upvotes: 3
Views: 2319
Reputation: 46020
Cocoa Bindings uses Key-Value Observing (KVO) to obtain notification of changes in model objects. In order for the change in the model (your BOOL
value) to be noticed by observers including any views that use bindings, you must update the model using Key-Value Coding-compliant accessor methods. If you just set the value of the ivar directly, no KVO notifications will be sent.
You can either implement the KVC accessors yourself or declare a property and use the @synthesize
keyword in your implementation to have the compiler create compliant accessors for you.
This is how you would implement KVC-compliant accessors:
//YourModel.h
@interface YourModel : NSObject
{
BOOL enabled;
}
- (BOOL)enabled;
- (void)setEnabled:(BOOL)flag;
@end
//YourModel.m
@implementation YourModel
- (BOOL)enabled
{
return enabled;
}
- (void)setEnabled:(BOOL)flag
{
enabled = flag;
}
@end
and this is how you would do the same thing using Objective-C 2.0 property syntax:
//YourModel.h
@interface YourModel : NSObject
{
BOOL enabled;
}
@property BOOL enabled;
@end
//YourModel.m
@implementation YourModel
@synthesize enabled;
@end
You can then call [yourModel setEnabled:YES]
and any registered KVO observers (including your menu binding) will be informed of the change.
Alternatively, you can call yourModel.enabled = YES
which will use the proper KVC accessors if available.
I uploaded a sample project to demonstrate how it's done.
Upvotes: 2