iOS 13 - 带占位符的 UITextField 应用崩溃
iOS 13 - UITextField with Placeholder getting app crash
在 iOS 13 中,访问 UITextField
_placeholderLabel.textColor 标签键时发生崩溃。
用于应用占位符文本颜色的键。
[textfield setValue:[UIColor whiteColor] forKeyPath:@"_placeholderLabel.textColor"];
"NSGenericException" - reason: "Access to UITextField's _placeholderLabel ivar is prohibited. This is an application bug"
您可以使用运行时来完成:
在placeholder setting底部添加如下代码
Ivar ivar = class_getInstanceVariable([UITextField class], "_placeholderLabel");
UILabel *placeholderLabel = object_getIvar(textField, ivar);
placeholderLabel.textColor = [UIColor whiteColor];
在Xcode11 beta2,这段代码可以用,但我不知道GM版或正式版。
完整代码:
- Objective-C版本
#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版本:
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更新
以上实现可以解决问题,但不提倡
使用私有 api 的应用程序将来可能会损坏。
请使用新的 api :
var attributedPlaceholder: NSAttributedString? { get set }
讨论
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.
完整代码:
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)
您可以使用 attributedPlaceholder
方法设置 UITextField
占位符文本颜色、字体,如下所示:
NSString *text = [textField text];
textField.attributedPlaceholder = [[NSAttributedString alloc] initWithString:text attributes:@{NSForegroundColorAttributeName: [UIColor redColor], NSFontAttributeName: [UIFont fontWithName:@"HelveticaNeue-Medium" size:14.0f]}];
我是这样做的:
对象
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
有点长,但我暂时没有更好的。
- Swift 版本
将以下代码添加到占位符设置的底部:
let iVar = class_getInstanceVariable(UITextField.self, "_placeholderLabel")!
let placeholderLabel = object_getIvar(textField, iVar) as! UILabel
placeholderLabel.textColor = .white
例如:
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
}
"Erase all contents and settings"
这对我有用。
Swift 5
这是 属性 的正确 Swift 替换。
请注意,如果您还更改了文本字段的其他属性的对齐方式,那么您也需要将这些属性设置为占位符的属性文本。通常只改变颜色和字体:
/// 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)
}
如果您使用的是 UITextView+Placeholder.h class 请更改以下方法 如果问题仍然存在请清理并构建
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;
}
用于 UISEARCHBAR 占位符 颜色
Xcode 11.1
从iOS13开始SDK提供UISearchBar.searchTextField所以我们可以使用
public API 而不是私有 API。在 UISearchBar 的子类中,我使用此代码更改占位符颜色
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"];
}
对于IOS13,您可以通过一行代码设置UITextField占位符颜色。
Objective C
[textField setAttributedPlaceholder:[[NSAttributedString alloc] initWithString:@"PlaceHolder Text" attributes:@{NSForegroundColorAttributeName:[UIColor whiteColor]}]];
在Swift 5
txtTitle.attributedPlaceholder = NSAttributedString(string:"PlaceHolder Text", attributes: [NSAttributedString.Key.foregroundColor: UIColor.white])
我认为这是 XCode 方面的错误,希望他们会在下一个版本中修复此错误。您可以通过擦除模拟器设备上的所有内容和设置来快速解决此问题。
我删除了 "User Defined Runtime Attributes" 部分中的变量“_placeholderLabel”
删除下划线“_”并试试这个。
[textfield setValue:[UIColor whiteColor] forKeyPath:@"placeholderLabel.textColor"];
它应该适用于所有版本!
是的,这个问题与 Xcode 版本有关。我有 Xcode 11.2.1,我面临着同样的问题。
_placeholderLabel.textColor
如果您从情节提要中将它用作运行时变量并遇到问题,那么只需删除“_”
那样
删除“_”运行时变量后开始工作
只需将 _placeholderLabel
替换为 placeholderLabel
从“_placeholderLabel.textColor”中删除“_”,尝试使用“placeholderLabel.textColor”。
在 iOS 13 中,访问 UITextField
_placeholderLabel.textColor 标签键时发生崩溃。
用于应用占位符文本颜色的键。
[textfield setValue:[UIColor whiteColor] forKeyPath:@"_placeholderLabel.textColor"];
"NSGenericException" - reason: "Access to UITextField's _placeholderLabel ivar is prohibited. This is an application bug"
您可以使用运行时来完成:
在placeholder setting底部添加如下代码
Ivar ivar = class_getInstanceVariable([UITextField class], "_placeholderLabel");
UILabel *placeholderLabel = object_getIvar(textField, ivar);
placeholderLabel.textColor = [UIColor whiteColor];
在Xcode11 beta2,这段代码可以用,但我不知道GM版或正式版。
完整代码:
- Objective-C版本
#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版本:
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更新
以上实现可以解决问题,但不提倡
使用私有 api 的应用程序将来可能会损坏。
请使用新的 api :
var attributedPlaceholder: NSAttributedString? { get set }
讨论
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.
完整代码:
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)
您可以使用 attributedPlaceholder
方法设置 UITextField
占位符文本颜色、字体,如下所示:
NSString *text = [textField text];
textField.attributedPlaceholder = [[NSAttributedString alloc] initWithString:text attributes:@{NSForegroundColorAttributeName: [UIColor redColor], NSFontAttributeName: [UIFont fontWithName:@"HelveticaNeue-Medium" size:14.0f]}];
我是这样做的:
对象
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
有点长,但我暂时没有更好的。
- Swift 版本
将以下代码添加到占位符设置的底部:
let iVar = class_getInstanceVariable(UITextField.self, "_placeholderLabel")!
let placeholderLabel = object_getIvar(textField, iVar) as! UILabel
placeholderLabel.textColor = .white
例如:
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
}
"Erase all contents and settings"
这对我有用。
Swift 5
这是 属性 的正确 Swift 替换。 请注意,如果您还更改了文本字段的其他属性的对齐方式,那么您也需要将这些属性设置为占位符的属性文本。通常只改变颜色和字体:
/// 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)
}
如果您使用的是 UITextView+Placeholder.h class 请更改以下方法 如果问题仍然存在请清理并构建
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;
}
用于 UISEARCHBAR 占位符 颜色
Xcode 11.1
从iOS13开始SDK提供UISearchBar.searchTextField所以我们可以使用 public API 而不是私有 API。在 UISearchBar 的子类中,我使用此代码更改占位符颜色
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"];
}
对于IOS13,您可以通过一行代码设置UITextField占位符颜色。
Objective C
[textField setAttributedPlaceholder:[[NSAttributedString alloc] initWithString:@"PlaceHolder Text" attributes:@{NSForegroundColorAttributeName:[UIColor whiteColor]}]];
在Swift 5
txtTitle.attributedPlaceholder = NSAttributedString(string:"PlaceHolder Text", attributes: [NSAttributedString.Key.foregroundColor: UIColor.white])
我认为这是 XCode 方面的错误,希望他们会在下一个版本中修复此错误。您可以通过擦除模拟器设备上的所有内容和设置来快速解决此问题。
我删除了 "User Defined Runtime Attributes" 部分中的变量“_placeholderLabel”
删除下划线“_”并试试这个。
[textfield setValue:[UIColor whiteColor] forKeyPath:@"placeholderLabel.textColor"];
它应该适用于所有版本!
是的,这个问题与 Xcode 版本有关。我有 Xcode 11.2.1,我面临着同样的问题。
_placeholderLabel.textColor
如果您从情节提要中将它用作运行时变量并遇到问题,那么只需删除“_”
那样
删除“_”运行时变量后开始工作
只需将 _placeholderLabel
替换为 placeholderLabel
从“_placeholderLabel.textColor”中删除“_”,尝试使用“placeholderLabel.textColor”。