In iOS 13, I'm getting a crash when accessing the UITextField _placeholderLabel.textColor label key.
The key used to apply placeholder text color.
[textfield setValue:[UIColor whiteColor] forKeyPath:#"_placeholderLabel.textColor"];
"NSGenericException" - reason: "Access to UITextField's _placeholderLabel ivar is prohibited. This is an application bug"
You can do it by using runtime:
add the following code to the bottom of placeholder setting
Ivar ivar = class_getInstanceVariable([UITextField class], "_placeholderLabel");
UILabel *placeholderLabel = object_getIvar(textField, ivar);
placeholderLabel.textColor = [UIColor whiteColor];
At Xcode 11 beta2 ,this code is work ,but I don't know about GM version or official version.
The complete code:
Objective-C Version
#import "ViewController.h"
#import <objc/runtime.h>
#interface ViewController ()
#end
#implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.view.backgroundColor = [UIColor grayColor];
self.title = #"UITextField Demo";
UITextField *textField = [UITextField new];
textField.frame = CGRectMake(0, 100, 300, 50);
textField.placeholder = #"UITextField Demo";
[self.view addSubview:textField];
Ivar ivar = class_getInstanceVariable([UITextField class], "_placeholderLabel");
UILabel *placeholderLabel = object_getIvar(textField, ivar);
placeholderLabel.textColor = [UIColor whiteColor];
}
#end
Swift Version:
import UIKit
class ViewController: UIViewController {
override func viewDidLoad() {
let textField = UITextField()
textField.frame = CGRect(x: 0, y: 100, width: 300, height: 50)
textField.placeholder = "UITextField Demo"
view.addSubview(textField)
let iVar = class_getInstanceVariable(UITextField.self, "_placeholderLabel")!
let placeholderLabel = object_getIvar(textField, iVar) as! UILabel
placeholderLabel.textColor = .red
}
}
2019/09/25 Update
The above implementation can solve the problem ,but it not be advocated.
The apps that use the private api maybe broken in the future.
Please use new api :
var attributedPlaceholder: NSAttributedString? { get set }
Discussion
This property is nil by default. If set, the placeholder string is drawn using system-defined color and the remaining style information (except the text color) of the attributed string. Assigning a new value to this property also replaces the value of the placeholder property with the same string data, albeit without any formatting information. Assigning a new value to this property does not affect any other style-related properties of the text field.
The complete code:
let textField = UITextField()
textField.frame = CGRect(x: 0, y: 100, width: 300, height: 50)
let placeholderString = NSAttributedString.init(string: "UITextField Demo", attributes: [NSAttributedString.Key.foregroundColor : UIColor.red])
textField.attributedPlaceholder = placeholderString
view.addSubview(textField)
I think it's a bug from the XCode side and hopefully, they will fix this one on the next release. You can quickly fix this by Erase all Contents and Settings on the Simulator device.
Yes this problem is related with the Xcode version. I have Xcode 11.2.1 and i am facing same issue.
_placeholderLabel.textColor
if you are using it from storyboard as runtime var and getting issue so just remove "_"
like that
after removing the "_" runtime Var start working
Remove Underscore "_" and try this.
[textfield setValue:[UIColor whiteColor] forKeyPath:#"placeholderLabel.textColor"];
It should work for all versions!
I did it this way :
Objc
NSMutableAttributedString *placeholderAttributedString = [[NSMutableAttributedString alloc] initWithAttributedString:searchField.attributedPlaceholder];
[placeholderAttributedString addAttribute:NSForegroundColorAttributeName value:[UIColor redColor] range:NSMakeRange(0, [placeholderAttributedString length])];
searchField.attributedPlaceholder = placeholderAttributedString;
Swift 5
var placeholderAttributedString = NSMutableAttributedString(attributedString: searchField.attributedPlaceholder)
placeholderAttributedString.addAttribute(.foregroundColor, value: UIColor.red, range: NSRange(location: 0, length: placeholderAttributedString.length))
searchField.attributedPlaceholder = placeholderAttributedString
It's a bit long but I have nothing better for the moment.
if you are using UITextView+Placeholder.h class please change below method Clean and build if issue persists
Objective C
+(UIColor *)defaultPlaceholderColor {
static UIColor *color = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
UITextField *textField = [[UITextField alloc] init];
textField.placeholder = #" ";
// color = [textField valueForKeyPath:#"_placeholderLabel.textColor"];
Ivar ivar = class_getInstanceVariable([UITextField class], "_placeholderLabel");
UILabel *placeholderLabel = object_getIvar(textField, ivar);
color = placeholderLabel.textColor;
});
return color;
}
You can set UITextField placeholder text color, font using attributedPlaceholder method as follows :
NSString *text = [textField text];
textField.attributedPlaceholder = [[NSAttributedString alloc] initWithString:text attributes:#{NSForegroundColorAttributeName: [UIColor redColor], NSFontAttributeName: [UIFont fontWithName:#"HelveticaNeue-Medium" size:14.0f]}];
"Erase all contents and settings"
This worked for me.
I removed the var "_placeholderLabel" in the section "User Defined Runtime Attributes"
Just replace _placeholderLabel with placeholderLabel
For IOS 13 you can set UITextField placeholder color by one line code.
Objective C
[textField setAttributedPlaceholder:[[NSAttributedString alloc] initWithString:#"PlaceHolder Text" attributes:#{NSForegroundColorAttributeName:[UIColor whiteColor]}]];
In Swift 5
txtTitle.attributedPlaceholder = NSAttributedString(string:"PlaceHolder Text", attributes: [NSAttributedString.Key.foregroundColor: UIColor.white])
- Swift Version
Add the following code to the bottom of placeholder setting:
let iVar = class_getInstanceVariable(UITextField.self, "_placeholderLabel")!
let placeholderLabel = object_getIvar(textField, iVar) as! UILabel
placeholderLabel.textColor = .white
For example:
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = .gray
let textField = UITextField()
textField.frame = CGRect(x: 0, y: 100, width: 300, height: 50)
textField.placeholder = "UITextField Demo"
view.addSubview(textField)
let iVar = class_getInstanceVariable(UITextField.self, "_placeholderLabel")!
let placeholderLabel = object_getIvar(textField, iVar) as! UILabel
placeholderLabel.textColor = .white
}
Swift 5
Here is a correct Swift replacement of that property.
Note that if you also change alignment of other properties for the text field, then you need to set these properties to placeholder's attributed text too. Usually only color and font are changed:
/// Set placeholder text color
/// - Parameter color: the color
func setPlaceholderColor(_ color: UIColor) {
// Color
var attributes: [NSAttributedString.Key: Any] = [.foregroundColor: color]
var range = NSRange(location: 0, length: 1)
// Font
if let text = attributedText, text.length > 0, let attrs = attributedText?.attributes(at: 0, effectiveRange: &range), let font = attrs[.font] {
attributes[.font] = font
}
else if let font = font {
attributes[.font] = font
}
self.attributedPlaceholder = NSAttributedString(string: self.placeholder ?? "", attributes: attributes)
}
FOR UISEARCHBAR PLACEHOLDER COLOR
Xcode 11.1
From iOS 13 onwards the SDK provides UISearchBar.searchTextField so we can use
public API instead of private API. In the subclass of UISearchBar i have used this code to change the placeholder color
UITextField *textField = [self findSubviewOfClass:[UITextField class]];
textField.textColor = [UIColor whiteColor];
//textField.font = [UIFont fontWithName:#"HelveticaNeue-Regular" size:14.0f];
if (#available(iOS 13.0, *)) {
self.searchTextField.attributedPlaceholder = [[NSAttributedString alloc] initWithString:self.placeholder attributes:#{NSForegroundColorAttributeName: [UIColor colorWithRed:0.8 green:0.82 blue:0.81 alpha:1]}];
}else {
[textField setValue:[UIColor colorWithRed:0.8 green:0.82 blue:0.81 alpha:1] forKeyPath:#"_placeholderLabel.textColor"];
}
Remove "_" form "_placeholderLabel.textColor" try with "placeholderLabel.textColor".
I created UISearchController programmatically and I had set frame for searchBar that I added in it. But the searchBar has wider frame and once I tap on it and tap on the cancel button with search bar; it regains the correct frame. How to set it correct at viewDidLoad?
Code is as such:
searchBar = [[UISearchBar alloc] initWithFrame:CGRectMake(0, 0, 310, 44)];
searchControllerMain = [[UISearchController alloc] initWithSearchResultsController:self.searchResultController];
searchControllerMain.searchBar.delegate = self;
searchControllerMain.searchResultsUpdater = self;
[searchControllerMain.searchBar sizeToFit];
[searchControllerMain.searchBar setPlaceholder:#"events"];
searchControllerMain.searchBar.barTintColor = [UIColor clearColor];
searchControllerMain.searchBar.searchBarStyle = UISearchBarStyleMinimal;
[[UITextField appearanceWhenContainedIn:[UISearchBar class], nil] setBackgroundColor:[UIColor lightGrayColor]];
[self.searchResultController.tableView reloadData];
UIView *searchBarContainer = [[UIView alloc] initWithFrame:searchBar.frame];
[searchBarContainer addSubview:searchControllerMain.searchBar];
self.navigationItem.rightBarButtonItem= [[UIBarButtonItem alloc] initWithCustomView:searchBarContainer];
Here's how I place a searchBar in the navigation item's titleView.
self.searchBar = [UISearchBar new];
self.searchBar.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
self.searchBar.searchBarStyle = UISearchBarStyleMinimal;
self.searchBar.placeholder = #"Search gospel events";
self.searchBar.delegate = self;
self.navigationItem.titleView = self.searchBar;
As you can see, I don't set a frame. It starts off with the right initial size, and will adjust sizes as orientation changes.
Have you tried setting an explicit autoresizingMask? I've never tried placing it in a custom bar button item, so I'm not sure if that will also fix your custom container issue.
Try this:
-(void)viewDidLayoutSubviews{
[super viewDidLayoutSubviews];
[searchControllerMain.searchBar setFrame:CGRectMake(0, 0, 310, 44)];
[searchControllerMain.searchBar setBounds:CGRectMake(0, 0, 310, 44)];
}
It worked for me!!
I am tyring to add UISegmentedControl to UIScrolview programmatically.
I am using below code..
I don't why the scrollview is not enabled.
UIScrollView *scroll = [[UIScrollView alloc] initWithFrame:CGRectMake(0, 0, 320, 435)];
scroll.contentSize = CGSizeMake(320, 700);
scroll.showsHorizontalScrollIndicator = YES;
NSArray *menu = [NSArray arrayWithObjects:[UIImage imageNamed:#"Accountimg.png"],[UIImage imageNamed:#"Challengesimg.png"],[UIImage imageNamed:#"Profileimg.png"],[UIImage imageNamed:#"Challengesimg.png"],nil];
UISegmentedControl *menuSegmentedControl = [[UISegmentedControl alloc] initWithItems:menu];
menuSegmentedControl.frame = CGRectMake(0,0,450,40);
menuSegmentedControl.segmentedControlStyle = UISegmentedControlStyleBar;
[scroll addSubview:menuSegmentedControl];
[menuScrollView addSubview:scroll];
[menuSegmentedControl release];
[scroll release];
I am unable to scroll horizontally..
Thanks in advance
UPDATE:
I am able to get the horizontal scroll.
Code updated:
menuSegmentedControl.frame = CGRectMake(0,0,500,35);
menuSegmentedControl.segmentedControlStyle = UISegmentedControlStyleBar;
menuScrollView.contentSize = CGSizeMake(menuSegmentedControl.frame.size.width, menuSegmentedControl.frame.size.height);
menuScrollView.showsVerticalScrollIndicator = NO;
[menuScrollView addSubview:menuSegmentedControl];
menuScrollView.clipsToBounds = YES;
Thank you.
"Now Playing" is in One line in UIBarButtonItem. I have to put it in two lines, like "Now" is ay top and "Playing" is at bottom.I have written the following line of code:-
UIBarButtonItem *flipButton = [[UIBarButtonItem alloc]
initWithTitle:#"Now Playing"
style:UIBarButtonItemStyleBordered
target:self
action:#selector(flipView)];
self.navigationItem.rightBarButtonItem = flipButton;
So i want to pu line break in between "Now Playing". So please help me out.
Yes you can. It is fairly simple to do. Create a multiline button and use that. The "trick" is to set the titleLabel numberOfLines property so that it likes multilines.
UIButton* button = [UIButton buttonWithType:UIButtonTypeCustom];
button.titleLabel.numberOfLines = 0;
[button setTitle:NSLocalizedString(#"Now\nPlaying", nil) forState:UIControlStateNormal];
[button sizeToFit];
self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithCustomView:button];
When you specify a button type of custom it expects you to configure everything... selected state, etc. which is not shown here to keep the answer focused to the problem at hand.
- (void)createCustomRightBarButton_
{
UILabel * addCustomLabel = [[[UILabel alloc] initWithFrame:CGRectMake(0, 0, 64, 25)] autorelease];
addCustomLabel.text =#"Now\nPlaying";
addCustomLabel.textColor = [UIColor whiteColor];
addCustomLabel.font = [UIFont boldSystemFontOfSize:11];
addCustomLabel.numberOfLines = 2;
addCustomLabel.backgroundColor = [UIColor clearColor];
addCustomLabel.textAlignment = UITextAlignmentCenter;
CGSize size = addCustomLabel.bounds.size;
UIGraphicsBeginImageContext(size);
CGContextRef context = UIGraphicsGetCurrentContext();
[addCustomLabel.layer renderInContext: context];
CGImageRef imageRef = CGBitmapContextCreateImage(context);
UIImage * img = [UIImage imageWithCGImage: imageRef];
CGImageRelease(imageRef);
CGContextRelease(context);
self.navigationItem.rightBarButtonItem = [[[UIBarButtonItem alloc] initWithImage:img
style:UIBarButtonItemStyleBordered
target:self
action:#selector(flipView)]
autorelease];
}
You can host a UIButton as customView inside your bar button (either set the bar button item customView or you can drag one directly on top of your UIBarButtonItem), hook it up as an outlet, then do;
-(void) viewDidLoad
{
//...
self.customButton.titleLabel.numberOfLines = 2;
self.customButton.suggestionsButton.titleLabel.lineBreakMode = UILineBreakModeWordWrap;
self.customButton.suggestionsButton.titleLabel.textAlignment = UITextAlignmentCenter;
}
which in my case becomes
I create 2 PNG images by myself, and it looks good.
UIImage *img = [UIImage imageNamed:#"nowplaying.png"];
UIBarButtonItem *nowPlayingButtonItem = [[[UIBarButtonItem alloc] initWithImage:img style:UIBarButtonItemStyleBordered target:delegate action:#selector(presentNowPlayingMovie)] autorelease];
In a TabBar-Application I have on the view a small one, in which I can draw. Works perfect.
With that code:
UITextField * textFieldRounded = [[UITextField alloc] initWithFrame:CGRectMake(10, 45.0, 260.0, 50)];
textFieldRounded.borderStyle = UITextBorderStyleRoundedRect;
textFieldRounded.textColor = [UIColor blackColor]; //text color
textFieldRounded.font = [UIFont systemFontOfSize:17.0]; //font size
textFieldRounded.placeholder = #"<enter text>"; //place holder
textFieldRounded.backgroundColor = [UIColor whiteColor]; //background color
textFieldRounded.autocorrectionType = UITextAutocorrectionTypeNo; // no auto correction support
textFieldRounded.keyboardType = UIKeyboardTypeDefault; // type of the keyboard
textFieldRounded.returnKeyType = UIReturnKeyDone; // type of the return key
textFieldRounded.clearButtonMode = UITextFieldViewModeWhileEditing; // has a clear 'x' button to the right
textFieldRounded.userInteractionEnabled = YES;
[skizzenFeldOutlet addSubview:textFieldRounded];
textFieldRounded.delegate = self;
I create a textfield. It works fine, but I can't put text on the textfield. The textfield is visible but I can draw in the view under the textfield!
Any tips?
Best regards
Andreas
because of this.
[skizzenFeldOutlet addSubview:textFieldRounded];
your textField is been flat added in your view.