Xcode 11 Beta - iOS 13 Simulator - UITextField with Placeholder getting app crash

人走茶凉 提交于 2019-12-05 11:06:52

问题


In Xcode 11 Beta Version and iOS 13 Simulator getting a crash when access TextField _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"


回答1:


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)




回答2:


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.




回答3:


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.




回答4:


"Erase all contents and settings"

This worked for me.




回答5:


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;

}



回答6:


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]}];



回答7:


Remove Underscore "_" and try this.

[textfield setValue:[UIColor whiteColor] forKeyPath:@"placeholderLabel.textColor"];

It should work for all versions!




回答8:


I have the same problem... maybe we just need to wait for beta 2




回答9:


- 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
}



回答10:


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)
}



回答11:


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"];

}



回答12:


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])



回答13:


I removed the var "_placeholderLabel" in the section "User Defined Runtime Attributes"



来源:https://stackoverflow.com/questions/56526966/xcode-11-beta-ios-13-simulator-uitextfield-with-placeholder-getting-app-cras

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!