Set the title of a UIButton with a single method invocation?
I'd like to set the title of a UIButton via code. I find myself having to call -[UIButton setTitle:forState:] for UI开发者_运维百科ControlStateNormal, UIControlStateHighlighted, UIControlStateDisabled, UIControlStateSelected. And that doesn't even take into account all of the combinations of these states together.
Needless to say, this is tiresome. Is there a single call I can make that will set one string as the title for all of the states? (Since, I assume that in 95% of the cases, that's the desired behavior?)
Yes, you certainly can. From the docs:
In general, if a property is not specified for a state, the default is to use the
UIControlStateNormal
value. If the value forUIControlStateNormal
is not set, then the property defaults to a system value. Therefore, at a minimum, you should set the value for the normal state.
So just set the title for UIControlStateNormal
and you're golden.
Like Mr./Ms. Frog says, setting the title for UIControlStateNormal will usually do the trick. The only exception is if titles are already set for other states. UIControlState is a mask, so you can cover your butt like so:
[button setTitle:@"Title" forState:UIControlStateNormal|UIControlStateHighlighted| UIControlStateDisabled|UIControlStateSelected]
If you're trying to be concise:
#define kAllControlStates (UIControlStateNormal|UIControlStateHighlighted| UIControlStateDisabled|UIControlStateSelected)
[button setTitle:@"Title" forState:kAllControlStates];
Or concise and opaque:
[button setTitle:@"Title" forState:0xffff];
Update: I should have tested this before answering. It turns out a mask like UIControlStateHighlighted|UIControlStateDisabled
indicates the state when the control is both highlighted and disabled. I had incorrectly assumed that that mask indicates "highighted or disabled". To conclude, you're better off with Mr. Frog's answer.
Create a category method for UIButton that sets it for all the states at once.
Although falling back to the values for the UIControlStateNormal state is probably good enough 99% of the time, I've come up with a solution to this problem for the 1% use case. (I have application defined states in a subclass which means falling back to the normal state would be incorrect.)
I'm posting it here for completeness, even though the answer has already been accepted. Basically it sets the attribute for the state plus every combination of individual additional states you specify.
@interface UIButton (AdditionalStates)
- (void)setTitle:(NSString *)title forState:(UIControlState)state additionalStates:(UIControlState)additionalStates;
@end
@implementation UIButton (AdditionalStates)
- (void)setTitle:(NSString *)title forState:(UIControlState)state additionalStates:(UIControlState)additionalStates
{
[self setValue:title forKey:@"title" state:state additionalStates:additionalStates mask:(1 << 0)];
}
- (void)setValue:(id)value forKey:(NSString *)key state:(UIControlState)state additionalStates:(UIControlState)additionalStates mask:(NSUInteger)mask(UIControlState)additionalStates
{
if (additionalStates == 0) {
[self setValue:value forKey:key state:state];
return;
}
// Iterate over each 'on' bit in additionalStates, starting from the mask bit
while (mask > 0) {
if (additionalStates & mask) {
// Delete the current bit from additionalStates
NSUInteger reducedAdditionalStates = (additionalStates ^ mask);
// Set the title for combinations of the remaining additional states with and without the mask bit
[self setValue:value forKey:key state:(state | (additionalStates & mask)) additionalStates:reducedAdditionalStates mask:(mask << 1)];
[self setValue:value forKey:key state:state additionalStates:reducedAdditionalStates mask:(mask << 1)];
}
mask = (mask << 1);
}
}
- (void)setValue:(id)value forKey:(NSString *)key state:(UIControlState)state
{
if ([key isEqualToString:@"title"]) {
[self setTitle:value forState:state];
return;
}
}
@end
精彩评论