Xcode 11 Beta - iOS 13 Simulator - UITextField с заполнителем, получая сбой приложения

В бета-версии Xcode 11 и симуляторе iOS 13 происходит сбой при доступе к ключу метки TextField _placeholderLabel.textColor.

Ключ, используемый для применения цвета текста заполнителя.

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

"NSGenericException" - причина: "Доступ к UITextField _placeholderLabel ivar запрещен. Это ошибка приложения"

Ответ 1

Вы можете сделать это с помощью среды выполнения:

добавьте следующий код в нижнюю часть настройки заполнителя

Ivar ivar =  class_getInstanceVariable([UITextField class], "_placeholderLabel");
UILabel *placeholderLabel = object_getIvar(textField, ivar);
placeholderLabel.textColor = [UIColor whiteColor];

На Xcode 11 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 }

Обсуждение

Это свойство по умолчанию равно nil. Если установлено, строка-заполнитель рисуется с использованием системного цвета и оставшейся информации о стиле (кроме цвета текста) приписанной строки. Присвоение нового значения этому свойству также заменяет значение свойства заполнителя теми же строковыми данными, хотя и без какой-либо информации о форматировании. Присвоение нового значения этому свойству не влияет на другие связанные со стилем свойства текстового поля.

Полный код:

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

Я сделал это так:

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

Это немного долго, но у меня нет ничего лучше на данный момент.

Ответ 3

"Удалить все содержимое и настройки"

Это сработало для меня.

Ответ 4

Вы можете установить цвет текста UITextField, шрифт, используя метод attributedPlaceholder следующим образом:

NSString *text = [textField text];
textField.attributedPlaceholder = [[NSAttributedString alloc] initWithString:text attributes:@{NSForegroundColorAttributeName: [UIColor redColor], NSFontAttributeName: [UIFont fontWithName:@"HelveticaNeue-Medium" size:14.0f]}];

Ответ 5

У меня такая же проблема... может нам просто нужно дождаться бета 2

Ответ 6

Пожалуйста, не используйте KVC для доступа к частным свойствам, это может измениться в любое время, используйте открытый API, как это (Swift 4+):

textField.attributedPlaceholder = NSAttributedString(string: "placeholder text", attributes: [NSForegroundColorAttributeName: UIColor.white])

Ответ 7

- Быстрая версия

Добавьте следующий код в конец настройки заполнителя:

    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
}

Ответ 8

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

Ответ 9

если вы используете класс UITextView + Placeholder.h, измените приведенный ниже метод очистки и сборки, если проблема не устранена

Цель 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;

}

Ответ 10

ДЛЯ UISEARCHBAR PLACEHOLDER ЦВЕТ

Xcode 11.1

Начиная с iOS 13 SDK предоставляет UISearchBar.searchTextField, поэтому мы можем использовать  публичный 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"];

}

Ответ 11

Для IOS 13 вы можете установить цвет заполнителя UITextField одной строкой кода.

Цель 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])