How to set UIButton title to null or an empty string - iphone

TL;DR - My question really is: How to I set a UIButton's title to an empty string, or null after it has already been assigned a previous title.
I have a UIButton that accepts a string generated based on the text from an NSString variable as it's title using the following:
NSString *MyStringVariable = #"HELLO";
...
[myButton setTitle:MyStringVariable forState:UIControlStateNormal];
For the sake of this question, let's just assume I have "HELLO" set on my NSString variable. This then makes my UIButton have the title "HELLO", obviously...
I then have another button which removes this title from the UIbutton, like so:
[myButton setTitle:#"" forState:UIControlStateNormal];
Which does hide the UIButton's title (i.e. it now just looks like an empty UIButton), but upon further inspection, the title does infact still exist. If I add the following to my UIViewController:
- (void)viewWillAppear:(BOOL)animated{
NSLog(#"Title: %#", myButton.titleLabel.text);
}
and navigate to and fro from this view, the title continues to get logged in the console, even though I've set the text to #"".
I have tried the following methods to make the title truly go away:
[myButton setTitle:#"" forState:UIControlStateNormal];
[myButton setTitle:NULL forState:UIControlStateNormal];
[myButton setTitle:nil forState:UIControlStateNormal];
myButton.titleLabel.text = #"";
The weird thing is, if I set the title to #" " (with a space):
[myButton setTitle:#" " forState:UIControlStateNormal];
the title does update correctly, and the space is then logged to the console, rather than the old title.
My question really is: How to I set a UIButton's title to an empty string, or null after it has already been assigned a previous title.

I too faced the same issue. I was setting the title of the button to #"" for all the states, and at a later point when I check the titlelabel.text it gives me the previous title which is not #"". So I printed out all the possible values of a button as suggested by PengOne and found that the properties titleForState and currentTitle give the updated/correct values.
So instead of checking the titleLabel.text, try checking the currentTitle or titleForState.
I still haven't figured out why the titleLabel is not updated properly.

I believe this has to do with how the UIButton updates its titleLabel property when setTitle:forState: is called.
For example, if you try to set the title of a button by directly accessing the titleLabel.text property, it does not work (check out the myriad questions on SO about this).
If you truly want to understand what's going on, then you should look at both the titleLabel.text and the current state of the button. One way to do this is to log titleLabel.text, currentTitle, and titleForState: in viewWillAppear, viewDidAppear, viewWillDisappear, and viewDidDisappear. The first two (titleLabel.text, currentTitle,) should coincide, and the third should be what you expect (titleForState:).

This sounds like a bug in the SDK, create a bugreport.
If you really need a button without a title, you'll probably have to create one yourself. A UIView with it's layer set to have a cornerRadius (and hence be rounded), which responds to user interaction should do it. Also, check the three20 toolkit, they may have a custom button or two in there you could use to save some time.

I have seen the same issue but in a different context. I have been using NSLocalizableString to change the text in a button.
It appears that setting the UIButton.title changes its UIButton.currentTitle but not its UIButton.titleLabel.text.
Though it may not make much of a difference for your application, the fact that titleLabel.txt and currentTitle are different turns to be more of a "be aware" than an implementation challenge.

Related

UIbutton label property

Just start to using Xcode. I made an IBOutlet from UIButton to have a possibility to change title with changing a localization setting. I try this code to do this
_loginButton.titleLabel.text = NSLocalizedString(#"Login", nil);
But this code does not set the button title. Do I need to use another kind of property?
Thank you very much for answering!
You need to supply a UIControlState to set the title for.
[_loginButton setTitle:NSLocalizedString(#"Login", nil) forState:UIControlStateNormal];
For UIButton, try setting the title like this:
[self.loginButton setTitle:NSLocalizedString(#"Login", nil) forState:UIControlStateNormal];
There are other states as documented here
But if you don't specify the title for those states, they will use the normal state by default.

Button title text not showing fully

I am using Xcode 4.2 iOS 5.0 and also using storyboard. I have simple button and I connected that button with outlet.Now I am changing the button text from code.Problem is that if my string of button title is that "hey how are you?" then it is showing in button title "hey....u?" .Can anyone suggest me where I am doing wrong or missing something else?
![enter image description here][1]This is IB Settings.I just wrote btw.textLabel.text=textstr; and frame is (0,0,290,42) and text str is time as for e.g [NSDate date]
Your button width is smaller than the title string's length.that's why
it truncates the middle part of the string. You can set the content
mode to characterWrap in IB to make the title in two lines or you can
change the font size to a smaller one to fit in your button width or
you can change the button width to occupy the whole string. Prefer
what is fine for you.
Try [myButton sizeToFit]; //I need to type 9 more characters to answer this question due to 30 char minimum.
I'm not sure if this already worked in XCode 4.2, but now it does ;)
You need to use the UIButton method setTitle:forState:
[self.myButton setTitle:#"Correct New Title" forState:UIControlStateNormal];
as this will correctly update the size and position of the buttons label. Where as just setting the title with self.myButton.titleLabel.text = #"Wrong New Title"; will not.
Credits to James Beith (see his Answer in UIButton - text truncated)
myButton.textLabel.text = #"some very long title";
[myButton.textLabel sizeToFit];
FOR SWIFT 4,5
You need to use "setTitle" instead of "textLabel.text"
Button.setTitle("this is maximium line text come", for: .normal)

UIButton setImage not working

I'm losing my mind over this one. I have UIButton connected as Outlet. I want to change it's image. In the viewDidLoad function, I try to set the image like so:
[button1 setImage:[UIImage imageNamed:#"house.png"] forState:UIControlStateNormal];
Nothing happens. However, if I use ImagePicker, it somehow works. In the ImagePickers function "didFinishPickingImage", I repeat the exactly same command as above for setting image and it works, the image is displayed normally.
I've been thinking that maybe the button's image is not refreshing itself, but trying to call [button1 setNeedsDisplay], or [button1.imageView setNeedsDisplay] or even [button1.imageView.image setNeedsDisplay] does nothing.
Does anyone have any idea about this? I've wasted two hours by now and I'm really getting frustrated, because I'm certain that the reason must be so stupid it's unbelivable.
Please check your button type.
If your button type is "System" you should change it to "Custom"
Two things to do here:
#1, change your code to:
[button1 setImage:[UIImage imageNamed:#"house.png"] forState:UIControlStateNormal];
and #2
make sure your UIImage returns a valid image.
In other words,
UIImage * imageToSet = [UIImage imageNamed: #"house.png"];
if(imageToSet)
{
[button1 setImage:[UIImage imageNamed:#"house.png"] forState:UIControlStateNormal];
} else {
// if you see this line in your console, then you know where to look for a problem
NSLog( #"why is my image object nil?");
}
For anyone who will find themselves in a similar situation; I was using the mentioned button inside a custom cell for table view. However, the cells aren't loaded right away (i.e. inside viewDidLoad/viewWillAppear etc.), but inside the tableView:cellForRowAtIndexPath function. All my button variables were nil at that point. My solution was to load the image after the cell has been created and it has worked straight away afterwards.
Here are a couple additional notes. UIButton setImage: forState: is the correct method:
[button1 setImage:[UIImage imageNamed:#"house.png"] forState:UIControlStateNormal];
imageNamed is a great convenience method for grabbing the image, but make sure it returns an object. Forgetting to include the image file in the current target gets me all of the time.
[UIImage imageNamed:#"house.png"]
You also don't need the extension. The SDK works this out.
[UIImage imageNamed:#"house"]
And even though UIControlState is a bit mask, you cannot OR the values together. This does not not not work and I must must must remember this because it gets me every time I use the call.
// NO NO NO
[button1 setImage:[UIImage imageNamed:#"house"] forState:UIControlStateNormal|UIControlStateSelected];
// YES
[button1 setImage:[UIImage imageNamed:#"house"] forState:UIControlStateNormal];
[button1 setImage:[UIImage imageNamed:#"house"] forState:UIControlStateSelected];
Was getting the same problem when UIbutton was in UITableViewCell.
UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
[button setImage:[UIImage imageNamed:#"detail.png"] forState:UIControlStateNormal];
should work in UITableViewCell
Glad to know that the problem is solved but none of the answers actually addresses the problem.
Generally, if the code is correct, then the error shifts from "syntax error" to the "logical error" category. There is no definite guide to handle it but here is a small checklist that can help anyone to troubleshoot their code.
1) The IBOutlet is not connected or renamed.
2) Make sure that the UIButton type is custom.
3) The image is set (more than once), somewhere else in the code.
4) You are trying to set the Image through any sync method which is not using the main thread. (There are several threads on that alone).
5) If you are nesting the images as subviews, make sure the problem isn't with their parent view.
6) If it is appearing in Simulator but not in the device, It's a lettercase (Uppercase, lowercase difference in the code and the filename.
7) Modern simulators works with very low GPU memory on older machines. You can tweak the simlator options to make it appear. E.g (Command + Right Arrow) twice to change the simulator orientation and your changes will appear.
There are few other but common pitfalls where developers usually overlook
1) The image doesn't exist OR you are making a spelling mistake.
2) The filetype is different than mentioned. (JPG, PNG).
Last thing you'll want to check - make sure you're setting the image on the main thread! Just ran into an issue where I was setting a button image in a callback from ALAssetLibrary (fetching images from photo library). The image wouldn't update until I tapped the button. Turns out the callback was happening off main...
for those having issues with system images not appearing, just use systemName: instead of named
if let starImg = UIImage(systemName: "star.fill") {
button.setImage(starImg, for: .normal)
}
It's for ios13 and later...
For me it was to move the line:
[button1 setImage:[UIImage imageNamed:#"house.png"] forState:UIControlStateNormal];
from awakeFromNib method
to viewDidLoad method
I guess,
don't create like this
UIButton *nextButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
by this create method ,UIButton is create by use default type,so your background image is not work.
try this,
UIButton *nextButton = [[UIButton alloc] initWithFrame:CGRectMake(9, 154, 300, 48)];
or other,except buttonWithType
This is happening because the state of the Button doesn't stays selected once clicked by default.
I solved it by making an IBaction on that button click and toggling the selected state.
-(IBAction) checkButtonClicked:(id)sender{
checkButton.selected = !checkButton.selected;
}
In my case, it is drawn by custom animation code and not set by the image, so it doesn't work by setting any image, it has to change the animation code.
With images, you have to import them into the project not as references but as copies. So when you go to add files to project, choose "Create groups" instead of "Create folder references". Also make sure "Copy items if needed" is checked.
This is confusing because importing as references works when you are using images as textures (e.g. for Sprites). However, it doesn't work when you want to use images for buttons (e.g. for using image name in [UIImage imageNamed:#"house.png"]
I faced this same issue of the image not being shown on the UIButton.
I had to change this line -
myButton.setImage(<my_UIImage_object>, for: [.normal, .focused])
to this -
myButton.setImage(<my_UIImage_object>, for: .normal)

Issues in setting UIButton title in its click event

I'm trying to change the title of a button when the user press on it with the following code:
- (IBAction) hideKB: (UIButton *) sender {
sender.titleLabel.text = #"↓";
}
But when I click the app crashes and I can't understand why.
Removing the sender stuff, the button works with no problems.
The correct method signature for an action is
- (IBAction)action:(id)sender
Your app is crashing because your object is being sent a message it doesn't understand.
Try replacing your code with something along the lines of:
- (IBAction)hideKB:(id)sender {
UIButton *button = (UIButton *)sender;
[button setTitle:#"↓" forState:UIControlStateNormal];
}
As you may notice I've also changed the line that sets the button title. This is because you should never manipulate a UIButton's titleLabel property directly, but rather you should be using the appropriate setter method as shown above.
Edit: To clarify, most controls will allow you to use dot notation to edit the text property of their titleLabel. However, UIButton instances support different titles (as well as images and background images) depending on the state they're in.
If you're wondering why a UIButton could be in one of several different states, a good example you often see is buttons that are "greyed out". What this means is that those buttons are in the UIControlStateDisabled state. You can find a list of all the possible states for a control in the documentation.
Try using
- (void)setTitle:(NSString *)title forState:(UIControlState)state
e.g.
[sender setTitle:"↓" forState:UIControlStateNormal];
you can try with:
[(UIButton *)sender setTitle: #"↓"" forState: UIControlStateNormal];
For more information, you can refer to setTitle:forState: in UIButton Class Reference
Hope this helps.

How to make UISlider's "track" invisible?

I'm trying to emulate Apple's "Slide to Unlock" feature in my application. I get to this point (image below), but as you can see the UISlider's "track" is visible and is covering up my text. Is there a way to change an attribute programmatically that will make the "track" invisible?
Please let me know if you need any of my code.
Thanks in advance!
EDIT: If I change the slider's alpha to 0, it gets rid of my sliding button, so doing that won't work unless I'm doing it wrong. :)
here's an even easier way. No need to create images, just instantiate an empty UIImage class :P
UIImage *clearImage = [[UIImage alloc] init];
[self.slider setMinimumTrackImage:clearImage forState:UIControlStateNormal];
[self.slider setMaximumTrackImage:clearImage forState:UIControlStateNormal];
Actually I just figured it out. Here's what I did:
UIImage *sliderMinimum = [[UIImage imageNamed:#"clearTrack.png"] stretchableImageWithLeftCapWidth:4 topCapHeight:0];
[slider setMinimumTrackImage:sliderMinimum forState:UIControlStateNormal];
UIImage *sliderMaximum = [[UIImage imageNamed:#"clearTrack.png"] stretchableImageWithLeftCapWidth:4 topCapHeight:0];
[slider setMaximumTrackImage:sliderMaximum forState:UIControlStateNormal];
clearTrack.png is just a clear slider image I made.
Now I have this: yay!
There probably isn't a way to hide the track; the "slide to unlock" doesn't behave like a UISlider and is probably a custom control. You might be able to hack the slider control, maybe by setting opacity low (0 will make it hidden and it won't receive touches), but if you go that route you will probably have something break after an OS update. Apple doesn't bend over backwards for compatibility like Microsoft does.
The right way to do this is with a custom control. It may seem like more work than using a UISlider, but it's not if you compare it against all the time you have spent and/or will spend hacking a UISlider.
To do it: subclass UIControl. Write your own drawing code to make it look right (you can probably reuse some of whatever you are doing now). Then register for touch events to move the slider handle:
UIControlEventTouchDown: if it's on the handle, set a "moving" flag
UIControlEventTouchDragInside: if the moving flag is set, move the handle to the touch position; you can just update an instance variable, call setNeedsDisplay to draw it in the new position.
UIControlEventTouchUpInside: if moving flag is set, and handle is at end, unlock
If you want to mimic the real unlock handle, play around with it and see how it behaves. You might need to respond to the events differently (what happens if you drag outside the slider path). But you should be able to get the gist of it.
In Swift:
slider.setMinimumTrackImage(UIImage(), forState: .Normal)
slider.setMaximumTrackImage(UIImage(), forState: .Normal)
In answer to the stated question, you can set a transparent 1px png for the minimum and maximum track images.
Looks like just setting the tint color to clear does it...
[slider setMinimumTrackTintColor:[UIColor clearColor]];
[slider setMaximumTrackTintColor:[UIColor clearColor]];
Answer by #Arjay Waran is the best in my opinion.
Heres the Swift 3.0 Version of it.
slider.minimumTrackTintColor = UIColor.clear
slider.maximumTrackTintColor = UIColor.clear
Cheers
From Story Board:-
select clear color for Min Track and Max Track