views:

526

answers:

2

I'm extending UIButton with generic functionality to change certain appearance attributes based on the displayed title.

In order to do this, I need to detect and respond to changes in the "state" property. This is so I make sure the appearance is adjusted properly if the user has set different titles for different states. I assumed I would need to use some sort of KVO like the following:

[self addObserver:self forKeyPath:@"state" options:NSKeyValueObservingOptionNew context:nil];

But this does not seem to fire the observeValueForKeyPath:... method for @"state" or @"currentTitle". I assume this is because UIButton does not implement the KVO pattern for those properties.

I do not want to just listen for clicks. Those events cause a state change, but are not the only potential causes.

Does anyone know a way to listen to and respond to state changes of a UIButton?

Thanks

A: 

Subclass UIButton, override setState: is what works for me. This is probably not the best way, but I have done it successfully.

Apologies for the above answer, it was wrong. Should have actually looked at my code. In my case, I only needed to change the state based on highlight, so I overrode -setHighlight: to change whatever values I needed. YMMV.

Steven Canfield
Just tried this and it does not work. The documentation for UIControl concurs: "This attribute is read only—there is no corresponding setter method."
DougW
+1  A: 

Alright I figured out a solution that works. You can listen to the text property of the button's titleLabel.

[self.titleLabel addObserver:self forKeyPath:@"text" options:NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld context:nil];

It seems to get fired twice per change, so you should check to make sure that the values of @"old" and @"new" in the passed change dictionary are different.

NOTE: Don't use @"old" and @"new" directly. The constants are NSKeyValueChangeOldKey and NSKeyValueChangeNewKey respectively.

DougW