Background: My company has support contracts for an app to always make it work for the two latest iOS versions. Now instead of updating the deployment target and building it with the newest iOS version they just checked if the app that was built with iOS7 and a deployment target of iOS5(!!!) still worked on iPads with the newest iOS. And with some adjustments they somehow managed to make it work.
Now it's all coming back: The app won't work for iOS11, it didn't even build for arm64 till now. And I got the awesome task of making it work.
Making the app build with arm64 wasn't even that hard, just had to replace some libraries. But when building for iOS11 the layout of the app is messed up. One small example: On the login screen we got some buttons that will just cut their labels for no apparent reason. There is enough space for the text but it's still cutting off. Everything else on this view is the same as before.
The code for the buttons (Interface Builder hasn't been used in this app) looks completely fine to me, it's pretty much the same how I would do it today. So my guess is that there are some build settings or similar stuff I have to change for it to look like it should. Can anyone give me a hint here on what to do?
If you want to check out the code for the button, here you go. I can't give you all the code I have since it's company code but this should be no problem:
loginButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
loginButton.titleLabel.font = BUTTON_FONT_SMALL;
loginButton.frame = CGRectMake(x, passwordField.frame.origin.y + passwordField.frame.size.height + spacerHeight * 2, fieldLength, labelHeight);
loginButton.backgroundColor = [UIColor clearColor];
loginButton.titleLabel.textColor = [UIColor blackColor];
[loginButton setTitleColor:[UIColor colorFromString:#"47;72;127"] forState:UIControlStateNormal];
[loginButton setTitleColor:[UIColor blackColor] forState:UIControlStateSelected];
[loginButton setTitleColor:[UIColor blackColor] forState:UIControlStateHighlighted];
[loginButton setBackgroundImage:buttonImageNormal forState:UIControlStateNormal];
[loginButton setBackgroundImage:buttonImageActive forState:UIControlStateSelected];
[loginButton setBackgroundImage:buttonImageActive forState:UIControlStateHighlighted];
loginButton.tag = 1;
[loginButton addTarget:self action:#selector(login_Tapped:) forControlEvents:UIControlEventTouchUpInside];
[[self view] addSubview:loginButton];
I want to implement tagging functionality like tumblr. I tried with UITextfield and added UIButtons for tags_name in textfield.
How to select tag on first back and delete it on second back?
How tags should be added in multiple lines in UITextfield?
please suggest any solution for this functionality.
here is the code how I added buttons in UItextfield with array.
for (count_value = 1; count_value<=[textfieldarray count]; count_value++)
{
UIButton *button_dish = [UIButton buttonWithType:UIButtonTypeRoundedRect];
[button_dish setTag:count_value];
[button_dish.layer setOpacity:0.5];
[button_dish.layer setCornerRadius:4.0f];
[button_dish setUserInteractionEnabled:YES];
[button_dish setShowsTouchWhenHighlighted:YES];
[button_dish setContentMode:UIViewContentModeCenter];
[button_dish setTitleEdgeInsets:UIEdgeInsetsMake(8, 8, 4, 8)];
[button_dish.titleLabel setLineBreakMode:NSLineBreakByWordWrapping];
[button_dish.titleLabel setFont:[UIFont fontWithName:#"Eau-SansBold" size:12]];
[button_dish setContentVerticalAlignment:UIControlContentVerticalAlignmentCenter];
[button_dish setContentHorizontalAlignment:UIControlContentHorizontalAlignmentCenter];
[button_dish setTitleColor:[UIColor redColor] forState:UIControlStateNormal];
[button_dish setContentMode:UIViewContentModeScaleAspectFit];
[button_dish setTitle:textfieldarray[count_value-1] forState:UIControlStateNormal];
CGSize expected_Size1 = [textfieldarray[count_value-1] sizeWithFont:button_dish.titleLabel.font constrainedToSize:button_dish.frame.size lineBreakMode:NSLineBreakByWordWrapping];
[button_dish addTarget:self action:#selector(buttonactionmethod:) forControlEvents:UIControlEventTouchUpInside];
left_view_length1 = left_view_length1+expected_Size1.width+16+12;
[iconview1 setFrame:CGRectMake(0, 10, left_view_length1, 24)];
[button_dish setFrame:CGRectMake(x_cordinate1, 2, expected_Size1.width+16, 20)];
x_cordinate1 = x_cordinate1+expected_Size1.width+16+12;
[iconview1 addSubview:button_dish];
[textfield1 setLeftView:iconview1];
}
Here is the sample reference image for tumblr tag,
1st image shows selection of button on first back.
2nd image shows multiple line tags.
Please give me some reference or hint.
That'd be called a "token field." They first appeared in Mail.app, and eventually became part of the AppKit framework. Documentation here.
It should be pretty easy to reproduce that look in Cocoa Touch. In Cocoa Touch, every view is backed by a Core Animation layer, and layers have a cornerRadius attribute according to your UI. Set that attribute to half the height of the field to create rounded ends. You can set a background color if you're okay with a flat appearance, or you can draw a subtle gradient to give a more convex appearance.
Of course, you only need to do all that if you want a reusable view where you can set the text and so forth. If you only need a few of these for custom buttons or something, it might be easier to just draw them in your favorite drawing program.
Another possibility is to use a third party control, such as any of:
TITokenField
JSTokenField
RMStokenview
COTokenField (part of COPeoplePickerViewController)
Reference from this SO Answer.
I'm trying to change the title of an UIButton I've created programmatically, when the user clicks in it. So, this is my code to create the UIButton:
myButton = [[UIButton alloc] initWithFrame:CGRectMake(0, 0, parentView.frame.size.width, parentView.frame.size.height)];
[myButton setBackgroundColor:[UIColor blackColor]];
[myButton setAlpha:0.7];
[myButton setTitle:#"Hello" forState:UIControlStateNormal];
[myButton addTarget:self action:#selector(userClicked:) forControlEvents:UIControlEventTouchUpInside];
[parentView addSubview:myButton];
And, in my userClicked: method, I do:
-(void) userClicked:(UIButton*)button
{
NSLog(#"USER CLICKED!!!");
if ([NSThread isMainThread])
{
NSLog(#"is main thread");
}
[button setTitle:#"Bye" forState:UIControlStateHighlighted];
[button setTitle:#"Bye" forState:UIControlStateNormal];
[button setTitle:#"Bye" forState:UIControlStateSelected];
[self someLengthyComputation];
}
The weird thing is that I can see the log messages printed:
USER CLICKED!!!
isMainThread
But, the title of the button does not change! What am I doing wrong?
EDIT: Setting the title for several states doesn't work either.
EDIT2: If I print the description of button in the debugger window of Xcode, it shows the right title!
Printing description of button->_titleView:
<UIButtonLabel: 0xa4c9310; frame = (95 216; 130 22); text = 'Bye'; clipsToBounds = YES; opaque = NO; userInteractionEnabled = NO; layer = <CALayer: 0xa44f080>>
This worked for me to update the title text (iOS 7.1, Xcode 5.1):
button.enabled = FALSE;
[button setTitle:#"Test" forState:UIControlStateNormal];
button.enabled = TRUE;
I was having the same problem, and I noticed that everywhere else I was setting the attributedTitle. So any updates to the title were not affecting the attributed title.
My solution:
[button setAttributedTitle:#"" forState:UIControlStateNormal];
instead of
[button setTitle:#"" forState:UIControlStateNormal];
At the moment, the shortest work around I came with is calling:
[button setNeedsLayout];
After updating the title.
This seems to happen in iOS 7.1.
All my buttons, which were behaving correctly in previous iOS versions (or maybe just compiled with previous SDKs) suddenly stopped doing that when compiled in Xcode 5.1.1 SDK 7.1.
Looks like Apple's bug.
I had a similar problem using storyboards. Using the answers above I had to use
[mybutton setTitle:#"SomeText" forState:UIControlStateNormal];
[button setNeedsLayout];
[button layoutIfNeeded];
AND I had to make sure that the button type was 'Custom' not 'System' in the attributes inspector.
Please see if this might help you...when the button is clicked check for condition if buttonToggled...like below when you have a function like changeButtonText
-(IBAction)changeButtonText:(id)sender {
if (!buttonToggled) {
[sender setTitle:#"Initial Text" forState:UIControlStateNormal];
buttonToggled = YES;
} else {
[sender setTitle:#"Alternative Text" forState:UIControlStateNormal];
buttonToggled = NO;
}
}
There are several issues in your code:
You are assigning callback to the button:
#selector(userClicked:)
but your code is in another method:
-(void)userTapOnTapToRefreshView:(UIButton*)button
To fix that you need to implement something like this:
-(void)userClicked:(id)sender
{
[(UIButton*)sender setTitle:#"Bye" forState:UIControlStateNormal];
}
Also this part of code does not make sense for me:
[parentView myButton];
Try to change it to:
[parentView addSubview:myButton];
Hope it will help :)
For Swift 3 to 5 just use the following:
button.setTitle("My title", for: .normal)
or for a attributed text use this:
button.setAttributedTitle(<AttributedString>, for: .normal)
This is kinda late and somewhat relates to Walter Schurter's response:
I had a similar issue where my button text was being set correctly until I updated to 7.1. Then I found that since my button was disabled, I had to set the title color and title text for the disabled state to get the text to show up. Then everything worked like a charm!
In iOS 7, UIButton's title is not updated when it is disabled. It seems like a bug on iOS 7.
As a workaround, update both normal and disabled title. It works!
[button setTitle:title forState:UIControlStateNormal];
[button setTitle:title forState:UIControlStateDisabled];
Try this:
[button setTitle:#"Bye" forState:UIControlStateHighlighted];
or:
[button setTitle:#"Bye" forState:UIControlStateSelected];
You could also modify your void function:
-(void) userClicked
{
NSLog(#"USER CLICKED!!!");
if ([NSThread isMainThread])
{
NSLog(#"is main thread");
}
[myButton setTitle:#"Bye" forState:UIControlStateNormal];
}
In my case I tried everything but nothing was working.
Then I just changed button type from system to custom from storyboard. BOOM! everything started behaving normally.
Change the button type to 'Custom', instead of 'System' and it will work as expected :)
Well, is all about the enabled state of a UIButton, Apple has changed something in 7.1 that does not allow you to change the title if you have the UIButton on a disabled state, thats all.
Thanks Apple, i have lost 10 min. debuging an app that was working fine.
Just found out this morning, got updated XCode yesterday to the 5.1.1 and iOS to 7.1
It could be the button layout refresh issue.....
Try using...
[button setNeedsLayout];
[button layoutIfNeeded];
It will force button to update the layout.
Finally, I've figured it out. There were two problems:
1) button was not in state UIControlStateNormal.
2) I was calling a method performing a long computation just after setting the title, [self someLengthyComputation].
I've solved the problem by:
1) Setting the title for all states of the button.
2) Performing that big computation in another thread, not the main thread.
My working code now is:
-(void) userClicked:(UIButton*)button
{
NSLog(#"USER CLICKED!!!");
if ([NSThread isMainThread])
{
NSLog(#"is main thread");
}
[button setTitle:#"Bye" forState:UIControlStateHighlighted];
[button setTitle:#"Bye" forState:UIControlStateNormal];
[button setTitle:#"Bye" forState:UIControlStateSelected];
dispatch_async(dispatch_get_global_queue( DISPATCH_QUEUE_PRIORITY_LOW, 0), ^{
[self someLengthyComputation];
});
}
Thank you very much to everybody who has answered/commented!
This may be trivial, but if you set some button image (instead of background image) which fills the whole button frame, this will shift the title right and thus make it invisible.
If so, try changing button image to background image.
Per Apple developer guide, you should not set either the button title label text or color directly as a property (for example, do not do this: myButton.titleLabel.text=#"SomeText" or myButton.titleLabel.textColor=[UIColor blackColor]).
Rather, you set them using the UIButton setter functionality, like this:
[myButton setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
...or like this:
[myButton setTitle:#"SomeText" forState:UIControlStateNormal];.
See the Apple guide.
Conclusion after trying many solutions is to use setAttributedTitle instead of setTitle.
To make the title string for AttributedString:
NSMutableAttributedString *attString = [[NSMutableAttributedString alloc] initWithString:#" new Test "];
[button setAttributedTitle:attString forState:UIControlStateNormal];
By the way, this problem is not occasionally happen in normal but it suddenly happen mainly for the following reasons:
If you change the enabled state of a UIButton and try to change the title.
If you use an attributed value and then want to change it using setTitle, the attributed value is superior to the title in that case.
If you navigate to another view controller and then return back to update the button title.
There is no requirement to use:
[button setNeedsLayout];
[button layoutIfNeeded];
Instead, first set type as DEFAULT to CUSTOM
If you applied setAttributedTitle then use:
[button setAttributedTitle:[NSAttributedString new] forState:UIControlStateNormal];
Otherwise there is no need to change anything.
If the color of the text has not changed then apply same thing and set title color with:
[button setTitleColor:[any_color] forState:UIControlStateNormal];
None of the above worked for my case (I was having a button on top of a view presented with UIPopoverController), and I had to removeFromSuperview before setTitle, then addSubview back - hope this helps someone with similar issues
I doubt if 'button' passed in as a parameter is myButton.Anyway,if myButton is a member var,you can just [myButton setTitle:#"Bye" forState:UIControlStateNormal];
Try to declare you button as a property, either in the interface or in the implementation part of you view / view controller
#property(nonatomic,strong) UIButton* myButton;
then create it
self.myButton = [[UIButton alloc] initWithFrame:CGRectMake(0, 0, parentView.frame.size.width, parentView.frame.size.height)];
[_myButton setBackgroundColor:[UIColor blackColor]];
...
It should work. Don't ask me why really - I just think it's all about ARC / Modern memory management..
EDIT:
It should also work if you keep a reference on the button in your implementation..
#implementation myViewController
{
UIButton* myButton;
}
-(void)createButton
{
myButton = [[UIButton alloc] initWithFrame:CGRectMake(0, 0, parentView.frame.size.width, parentView.frame.size.height)];
[myButton setBackgroundColor:[UIColor blackColor]];
...
}
...
instead of
yourButton.titleLabel?.text = "T"
use this
yourButton.setTitle("TITLE", for: .normal)
Always do addSubview before setting the text on UIButton.
i am totally confused.
I just want to set an Image for the Default-State of a list of UIButtons. But in does not work.
I simply assigned the image to all my Buttons inside the setter of my Outlet-Collection but the Image just appears if the Button is highlighted but I want that the Image always is set except the button is selected. This is my code so far :
-(void)setCardButtons:(NSArray *)cardButtons
{
UIImage * cardBackImage = [UIImage imageNamed:#"card-back.jpg"];
for (UIButton * button in cardButtons) {
[button setImage:cardBackImage forState:UIControlStateNormal|UIControlStateHighlighted];
[button setImage:nil forState:UIControlStateSelected];
}
_cardButtons = cardButtons;
}
I really dont know what i am doing wrong ? How can i set the Image of my Default-State-Button without using the IB ?
There are a few states you can use, make sure you set them correctly. Copy and paste this into Xcode and fill in your images by tabbing through.
Might be worth while refreshing your memory by reading the Apple Doc for this.
[button setImage:<# normal image #> forState:UIControlStateNormal];
[button setImage:<# selected image #> forState:UIControlStateSelected];
[button setImage:<# highlighted image #> forState:UIControlStateHighlighted];
[button setImage:<# selected and highlighted image #> UIControlStateSelected | forState:UIControlStateHighlighted];
Have you tried with only:
[button setImage:cardBackImage forState:UIControlStateNormal];
[button setImage: [UIImage imageNamed:#"Back.png"] forState:UIControlStateNormal];
[button setTitle: #"Title" forState:UIControlStateSelected];
I would like the button to display the image in normal state but the word "Title" in selected state. But I can't get this code to work. It displays Image when I click the button to selected state and the Image covers the title. I can't get rid of the image in selected state.
[button setImage: [UIImage imageNamed:#"Back.png"] forState:UIControlStateNormal];
[button setImage: [UIImage imageNamed:#"Back2.png"] forState:UIControlStateSelected];
But this works. The image flips from Back to Back2. Or the other way works too
[button setImage: [UIImage imageNamed:#"Back.png"] forState:UIControlStateSelected];
[button setTitle: #"Title" forState:UIControlStateNormal];
It is so simple and I started to think it is UIButton bug.
Has anyone tried this before?
Add some small transparent image (1px is enough) to your project and name it, for example, transparent.png. Then add this line to the code:
[button setImage: [UIImage imageNamed:#"transparent"] forState:UIControlStateSelected];
The other and much simpler solution is to use interface builder and set images for diferent states. In this case you even don't need to use the transparent image; simply left the Image field empty for Selected state.
Like #codeplasma answer, but no need to add a transparent image, just create an empty UIImage:
button.setImage(UIImage(), forState: .selected)
In Objective-C you would create it with [UIImage new].
You have to explicitly set the button state to selected in some UIButtons(like the rounded rect button), it does not happen automatically upon clicking on it.
Bug?
No, it's not a bug, UIButton is designed this way, and here's why: when you set an image for the UIButton's UIControlStateNormal (normal state), it will preserve it throughout the other states (selected, disabled, highlighted) in the event you did not specify an image for those other states.
This means you can set up your button with a single image, the system adds a dark highlight in highlight state and makes the button look like it's alpha 0.5 in disabled state.
You might think setting the image to nil for the selected state will get rid of it for that state, but of course when the state changes, it will see that it doesn't have an image for that state (it's nil !), but it does for state UIControlStateNormal, so it will use that one instead, thus you are stuck with the same image!
Note that if you set the image for a different state then normal, it would have only shown for that state.
Workaround
Honestly your intentions with the button's image/title sound a little odd... Maybe you're new to iOS, maybe with some more info about what your button is and is supposed to be doing, we can suggest a better solution.... but the easiest way to workaround this with the information you've given us is to give a valid image for the selected state, one which is preferably transparent, and it could be 1x1 pixels also to save on space.
Otherwise you can do this, create a UIImage at runtime to use as a placeholder acting as your image, but would be a good idea to cache this, perhaps create it once and hold it in an iVar.
// Create a 1x1 UIImage at runtime
UIGraphicsBeginImageContext((CGSize){1.0f,1.0f});
UIImage *runtimeImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
// Setup your button
UIButton *btn = [UIButton buttonWithType:UIButtonTypeRoundedRect];
btn.frame = CGRectMake(20.0, 20.0, 100.0, 100.0);
// set the image for each state
[btn setImage:[UIImage imageNamed:#"Back.png"] forState:UIControlStateNormal];
[btn setImage:runtimeImage forState:UIControlStateSelected];
// have your text for the normal state
[btn setTitle:#"selected !" forState:UIControlStateNormal];
Instead of using setImage, I suggest to use SetBackgroundImage for this scenario. Here is a solution that works for me for a similar solution:
UIImage *cardBackImage = [UIImage imageNamed:#"card.png"];
UIImage *cardFrontImage = [UIImage imageNamed:#"transparent.png"];
[cardButton setBackgroundImage:cardFrontImage forState:UIControlStateSelected];
[cardButton setBackgroundImage:cardFrontImage forState:UIControlStateSelected|UIControlStateDisabled];
[cardButton setBackgroundImage:cardBackImage forState:UIControlStateNormal];