André Pareis
André Pareis

Reputation: 1094

How to bind NSButton enabled state to a composed condition

This is my situation in Xcode Interface Builder:

IB situation

There is also an NSArrayController in entity mode which controls the content of the NSTableView. I want to enable the 'Create' button when the NSTableView is empty (as controlled by the NSSearchField) AND when the text in the NSSearchField is not empty. How do I achieve that? Is it possible without programming?

To what KVO compliant values can I bind the 2 enabled conditions of the 'Create' button?

Upvotes: 2

Views: 2243

Answers (3)

Vince
Vince

Reputation: 575

You seems to have a window, so presumably you have a controller object which is set as the File's Owner for the NIB file.

Why not declare a boolean property in this controller class, that returns a value based whatever conditions you want ?

@property(readonly) BOOL canCreate;

That you implement :

-(BOOL)canCreate {
    // compute and return the value
}

Be sure to send KVO notifications appropriately when the conditions for the creation change.
The last step is to bind the button's enabled binding on the File's Owner canCreate key.

Upvotes: 1

XelharK
XelharK

Reputation: 609

I'm SOOO late for this, but came up with another method and just tested it in my app. It works, so I'm going to share it for anyone who will find this question in the future.

Basically what you want to do is to create a property WITHOUT a corresponding value in your controller

     @property (readonly) BOOL enableProperty;

This means that there's actually no

    BOOL enableProperty;

defined in the header file, or anywhere

then, rather than synthesize it, just write your own getter, and put there your condition

    - (BOOL) enableProperty{
        return (condition);
    }

Third step: anytime there's the chance that your condition changes, notify it.

    - (void) someMethod{
        //.... Some code
        [self willChangeValueForKey:@"enableProperty"];
        [Thisline mightChange:theCondition];
        [self didChangeValueForKey:@"enableProperty"];
        //.... Some other code
    }

fourth step: in IB, bind your control's enabled property to this "fake" property.

Enjoy! ;)

Upvotes: 3

Francis McGrew
Francis McGrew

Reputation: 7272

I don't think there's a way to do it entirely in interface builder, but with a small amount of code you can get it working pretty easily. First, make sure your controller (or App Delegate) is set as the delegate of the search field, and that it has IBOutlet connections to the search field, the button and the array controller. Here's how I would implement it:

// This is an arbitrary pointer to indicate which property has changed.
void *kObjectsChangedContext = &kObjectsChangedContext;

- (void)awakeFromNib {

    // Register as an observer so we're notified when the objects change, and initially at startup.
    [arrayController addObserver:self
                      forKeyPath:@"arrangedObjects"
                         options:NSKeyValueObservingOptionInitial
                         context:kObjectsChangedContext];
}

// This updates the button state (based on your specs)
- (void)updateButton {

    BOOL canCreate = (searchField.stringValue.length > 0 &&
                      0 == [arrayController.arrangedObjects count]);
    [createButton setEnabled:canCreate];
}

// This delegate method is called whenever the text changes; Update the button.
- (void)controlTextDidChange:(NSNotification *)obj {
    [self updateButton];
}

// Here's where we get our KVO notifications; Update the button.
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {

    if (kObjectsChangedContext == context)
        [self updateButton];

    // It's good practice to pass on any notifications we're not registered for.
    else {
        [super observeValueForKeyPath:keyPath ofObject:object change:change context:context];
    }
}

If you're new to bindings some of that may look like Greek, hopefully the comments are clear enough.

Upvotes: 3

Related Questions