Difference between setTitle:forState: and titleLabel.text - ios

After looking over the internet and other SO questions(this one is great iOS: UIButton titleLabel -- does it do anything at all?), it is unclear to me what is the difference between these two, more accurately, how these two work.
I know that setTitle:forState: let me set text of the button for different states(Normal, Disabled,Highlighted etc.). I know, as well, that titleLabel is read only, but its properties are read/write.
At this point you might ask: What is the problem then?
I will explain it through example. I have following hierarchy:
UITableViewCell - MyView - MyButton
MyView is xib in which, through interface builder, I set button. When I set buttons title like:
self.myButton.titleLabel.text = #"Something"; // some string I get from server
It works. But if I try the similar approach when only MyView is included (somewhere else in the project) and try:
myView.myButton.titleLabel.text = #"Something else";
It doesn't work. Let me be more specific. In one part of the second(even in viewDidApper) buttons title is what I want. After that, the buttons label returns to its default value. The one I set in the interface builder. When I change to
[myView.myButton setTitle:#"Something else" forState:UIControlStateNormal];
It works as expected.
What I want to know is why does this happen? It is unclear to me why does this glitch occurs with the title? Is this strange thing documented somewhere(looked over apple documentation)? Is it possible to get implementation of setTitle:forState:?

I'm not sure how the internals of UIButton are actually implemented but this is a guess. There are times when iOS needs to redraw the button ie. the button is tapped so the button's state changes (let's say from UIControlStateNormal to UIControlStateHighlighted). Then iOS would find the title associated to UIControlStateHighlighted then display that text by using something like.
myButton.titleLabel.text = #"Title for UIControlStateHighlighted";
Sample scenario:
[myButton setTitle:#"Normal" forState:UIControlStateNormal];
[myButton setTitle:#"Highlighted" forState:UIControlStateHighlighted];
// somewhere in the code, you call this to change the label
myButton.titleLabel.text = #"Something else";
// when user taps the button, iOS will do something like
myButton.titleLabel.text = #"Highlighted"; // will overwrite "Something Else"
// when user releases, iOS will again do something like
myButton.titleLabel.text = #"Normal"; // will overwrite "Highlighted"
so it's required to use setTitle:forState: in order to associate the given title to a certain state. The instances where iOS redraws the button is of course not limited to the the user interacting with the button. It could also be triggered by layout changes.

You should not use button.titleLabel.text = to set the button title.
The documentation for the titleLabel property says
Although this property is read-only, its own properties are read/write. Use these properties primarily to configure the text of the button. For example:
UIButton *button = [UIButton buttonWithType:UIButtonTypeSystem];
button.titleLabel.font = [UIFont systemFontOfSize: 12];
button.titleLabel.lineBreakMode = NSLineBreakByTruncatingTail;
Do not use the label object to set the text color or the shadow color. Instead, use the setTitleColor(:for:) and setTitleShadowColor(:for:) methods of this class to make those changes. To set the actual text of the label, use setTitle(_:for:) (button.titleLabel.text does not let you set the text).

I normally don't set button titles in interface builder, but do it in the viewDidLoad, and get the title from Localizable.strings..
You must use setTitle:forState and setTitleColor:forState to change text and color. All other label properties can be changed directly though.
"Do not use the label object to set the text color or the shadow color. Instead, use the setTitleColor:forState: and setTitleShadowColor:forState: methods of this class to make those changes."
-source

Related

setImage:forState does not work for subclass of UIButton

I create a class RadioButton that inherited from UIButton ,and rewrite the method layoutSubViews where reset the frame of self.imageView and self.titleLabel ,when I call the method setImage:forState: of RadioButton instance,it does not work, but the method radioButton.imageView.image = [UIImage imageNamed:#""] work. It is an interesting problem ,I appreciate so much if anyone know why and share the reason .
When we set title,image for button we need to use below code
For Button
[button setTitle:#"Your Title" forState:UIControlStateNormal];
For Image
[button setImage:[UIImage imageNamed:#"Your Image Name"] forState:UIControlStateNormal];
why should not we use titleLabel
Do not use the label object to set the text color or the shadow color.
Instead, use the setTitleColor:forState: and
setTitleShadowColor:forState: methods of this class to make those
changes.
The titleLabel property returns a value even if the button has not
been displayed yet. The value of the property is nil for system
buttons.
why should we use setTitle
Use this method to set the title for the button. The title you
specify derives its formatting from the button’s associated label
object. If you set both a title and an attributed title for the
button, the button prefers the use of the attributed title over this
one.
At a minimum, you should set the value for the normal state. If a
title is not specified for a state, the default behavior is to use the
title associated with the UIControlStateNormal state. If the value for
UIControlStateNormal is not set, then the property defaults to a
system value.
For Image

UIButton Multiple Labels Using UIControlStates

I know with a UIButton, I can add additional UILabels as subviews:
[myButton addSubview: myLabel];
And (at least, with the default title label) I can set its text color when tapped by using:
[myButton setTitleColor:someColor forState:UIControlStateHighlighted]
My question is, how can I implement this functionality for additional UILabels added to the UIButton (if this is possible)?
Subclass UIButton and add your additional labels in there as instance variables. Then override -setHighlighted and -setSelected to adjust the additional labels as desired.
FYI - you call [myButton setTitleColor...], not [myButton.titleLabel setTitleColor...]
It seems my way of going about it isn't easy, but I realized I can just add an action to the UIButton for the event UITouchDown, and change the labels accordingly in the action.
You would have to set myLabels text color, before you added it as a subView.
Otherwise, you'll have to enumerate through the button's subviews and change each of your added label's text colors.
Update:
You can change the button title's font as follows:
myButton.titleLabel!.font = UIFont(name: "...", 10)
You can change the button's title color as follows:
colorsBtn.setTitleColor(UIColor.brownColor(), forState: UIControlState.Highlighted)

How can I change a UILabel's text color back to what it was when the program first launched in Xcode for iOS 7?

When programming in Obj-C for iPhone, it is often necessary to adjust the text color of objects such as labels, buttons, etc. I get that we usually do this by using code like:
myLable.textColor = [UIColor redColor];
Now my problems arise when the color I started with is not one of the pre-defined UIColors. I can change its text's color to any of the pre-defined (as in this case, red), but how can I revert the color to the one I chose in the storyboard (the color of the label's text as the program first starts)?
Thanks in advance for your help!
As my comment suggests, you should create a property to later access your custom color like this:
#property (nonatomic, strong) UIColor *myColor;
- (void)viewDidLoad
{
// Set the values as the ones in storyboard. Make sure to always divide by 255.0!
self.myColor = [UIColor colorWithRed:(255.0/255.0) green:(59.0/255.0) blue:(48.0/255.0) alpha:1.0];
// Set the label's text color property to our custom color.
myLabel.textColor = self.myColor;
}
In storyboard, click here to find the exact color you need:

UIButton title appears with dots when set programatically

When I set the title of the UIButton in the xib, it works fine, but when I set the same text programatically to the title of the button it is trimmed.
BUY THIS FILM FOR 20.00$ -> BUY THIS FI...FOR 20.00$
Try this way:
[_button setTitle:#"BUY THIS FILM FOR 20.00$" forState:UIControlStateNormal];
What is displayed in interface builder when you edit the xib is not guaranteed to look exactly like when it is loaded on the simulator or device.
Solution: just make your Button a little bit wider.
Also, double check that the text is exactly the same as in IB.
Try this way:
btnObj.titlelabel.minimumFontSize = 8.0; // or some more adequate size
btnObj.titleLabel.adjustsFontSizeToFitWidth = YES;

titleLable.text not working

I create an UIButton and use titleLable.text to set text ,but the text is not seen in the button so I replace it with setText method, and it show the text, I just want to know why the titleLable.text is not working
UIButton *button=[UIButton buttonWithType:UIButtonTypeCustom];
button.titleLabel.text=#"text";
Then used like below
[button setTitle:#"text" forState:UIControlStateNormal];
Because titleLabel is a readonly property.
titleLabel
A view that displays the value of the currentTitle property for a
button. (read-only)
#property(nonatomic, readonly, retain) UILabel *titleLabel >
Discussion
Although this property is read-only, its own properties are
read/write. Use these properties primarily to configure the text of
the button. For example:
UIButton *button = [UIButton buttonWithType: UIButtonTypeRoundedRect];
button.titleLabel.font = [UIFont systemFontOfSize: 12];
button.titleLabel.lineBreakMode = UILineBreakModeTailTruncation;
Do not use the label object to set the text color or the shadow color.
Instead, use the setTitleColor:forState: and
setTitleShadowColor:forState: methods of this class to make those
changes.
The titleLabel property returns a value even if the button has not
been displayed yet. The value of the property is nil for system
buttons.
Availability
Available in iOS 3.0 and later.
Declared In UIButton.h
Please refer UIButton Class for more details.
Midhun's answer, while completely true, doesn't answer the question. As he says, the label property is read-only but its properties are not, including the text property.
The reason setting the text does not work is that the button itself will be setting the text internally, depending on the control state. This will override anything you've set as the text.
This is why you use setTitle:forControlState: instead. The button will use the value for the normal state for all other states, unless you tell it otherwise, but if you never set a title for any control state, it will not show the label.

Resources