Question

I have a very simple question I hope someone can answer as I start understanding bindings. I want to programmatically change my NSString value and have the NSTextField update to that value thru bindings. I have a NSTextField and NSLabel. To represent the value of the myString properly changing I have a NSButton.

  • I have NSTextField's Value bound to myString property of App Delegate with Continuously Update Value checked.
  • I have NSLabel's Value bound to myString Property of App Delegate.
  • I have NSButton outlet hooked to setDefault method.

When I type in NSTextField the NSLabel updates as expected but when I click the button the myString property is updated but not in the NSTextField.

What do I need to do to get the NSTextField update to the myString property????

AppDelegate.h

@interface AppDelegate : NSObject<NSApplicationDelegate>
{
   NSString *myString;
}

@property (assign) IBOutlet NSWindow *window;
@property NSString *myString;

- (IBAction)setDefault:(id)sender;
@end

AppDelegate.m

@implementation AppDelegate

@synthesize window = _window;
@synthesize myString;

- (void)applicationDidFinishLaunching:(NSNotification*)aNotification
{
   myString = @"This is a string";
}

- (IBAction)setDefault:(id)sender
{
   NSLog(@"%@", myString);
   myString = @"This is a string";
   NSLog(@"%@", myString);
}
@end
Was it helpful?

Solution

It shouldn't be

myString = @"This is a string";

but this:

self.myString = @"This is a string";

both in -applicationDidFinishLaunching: and in -setDefault:. Don't forget to specify self in your NSLog statements as well. You'd probably like to specify a different string in -setDefault: so that you can actually see that a change is taking place.

One other thing: You're effectively saying that you want to assign to myString, but that's not appropriate for an object. Instead of:

@property NSString *myString;

you should instead use

@property (copy) NSString *myString;

or at least

@property (retain) NSString *myString;

The former is preferred because passing a NSMutableString instance effectively copies it as a NSString, while passing a NSString instance simply retains it.

Good luck to you in your endeavors.

OTHER TIPS

I recommend that you prefix your member variables. This way you can distinguish between setting the member directly or using the setter. In your example I would do the following.

@interface AppDelegate : NSObject<NSApplicationDelegate>
{
   NSString *m_myString;
}

@property (assign) IBOutlet NSWindow *window;
@property NSString *myString;

- (IBAction)setDefault:(id)sender;
@end

...

@implementation AppDelegate

@synthesize window = _window;
@synthesize myString = m_myString;

- (void)applicationDidFinishLaunching:(NSNotification*)aNotification
{
   self.myString = @"This is a string";
}

- (IBAction)setDefault:(id)sender
{
   NSLog(@"%@", m_myString);
   self.myString = @"This is a string";
   NSLog(@"%@", m_myString);
}
@end

Notice, that I changed the @synthesize to assign the member variable.

To clarify:

self.myString = @"This is a string";

.. is an alternative syntax for ...

[self setMyString:@"This is a string"];

You can also set the member directly ...

[self willChangeValueForKey:@"myString"];
m_myString = @"This is a string";
[self didChangeValueForKey:@"myString"];

But then you need to "inform" observers of the binding as illustrated above.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top