IOS 13 — UITextField с заполнителем вызывает сбой приложения

В 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"

Эта проблема существует и в Семена Xcode 11 GM.

Sunil Targe 20.09.2019 12:01

@SunilTarge проверить ответы - stackoverflow.com/a/56776561/3560390

PrasathBabu 20.09.2019 12:57

Это не "проблема". Запрещено ковыряться во внутренних деталях реализации. Вы нарушаете правила App Store. Любой «обходной путь», который вы попытаетесь сделать, скоро снова будет сломан. Останавливаться.

russbishop 24.09.2019 05:19

@PrasathBabu это замораживание предназначено только для симулятора, верно? пока в реальном устройстве не зависает, то это не проблема? Я начинающий. Я смущен, потому что у меня нет этого зависания на реальном устройстве, а только в симуляторе. так что, если меня не волнует симулятор, мне не нужно добавлять ответы ниже, верно? пожалуйста, очень нужна ваша информация

Alexa289 21.10.2019 02:24

@ Alexa289 Alexa289 На устройстве происходит сбой — когда вы создаете приложение с помощью Xcode11 и iOS 13 Device. Сбой не происходит, если приложение собирается до Xcode11 и устанавливается на устройство iOS 13.

PrasathBabu 22.10.2019 13:40

@PrasathBabu Я не пробовал на iOS 13, но только что попробовал на iOS 13.1.3 и не обнаружил проблем на своем реальном устройстве. просто зависаю на симуляторе. вот почему у меня есть сомнения, добавлять код ниже (ответ) или нет

Alexa289 22.10.2019 13:51
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
27
6
22 138
15
Перейти к ответу Данный вопрос помечен как решенный

Ответы 15

Ответ принят как подходящий

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

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

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
  • Быстрая версия:
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)

Спасибо. Эта «ошибка» все еще существует в бета-версии 6. Написал это на Swift и работает там же.

Chris Paveglio 09.08.2019 21:14

С какой стати вы рекомендуете людям делать что-то явно недопустимое, публикуя другой обходной путь? Это не нормально, прекратите это делать. Ваши приложения будут сломаны в будущем.

russbishop 24.09.2019 05:15

@russbishop какое-нибудь решение, как его изменить? Спасибо

Tieda Wei 25.09.2019 02:16

@russbishop Спасибо, что напомнили. Я обновил свой ответ.

iDevOrz 25.09.2019 08:43

@iDevOrz четко написано в документах: «Если установлено, строка-заполнитель рисуется с использованием определенного системой цвета и оставшейся информации о стиле (кроме цвета текста)». Значит, вы не ответили на вопрос в своем обновлении.

Mikhail Maslo 25.09.2019 12:17

Изменение цвета текста заполнителя не поддерживается UIKit, но отзывы об этом приветствуются. Вы можете использовать attributedPlaceholderString для изменения атрибутов стиля разное текста-заполнителя.

russbishop 25.09.2019 22:25

@Mikhail Maslo, спасибо за напоминание,Но когда я встраиваю Xcode 11 и запускаю iOS 12.2 и iOS 13 Simulator, у меня это сработало. Как это странно!

iDevOrz 26.09.2019 06:26

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

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;

Свифт 5

var placeholderAttributedString = NSMutableAttributedString(attributedString: searchField.attributedPlaceholder)
    placeholderAttributedString.addAttribute(.foregroundColor, value: UIColor.red, range: NSRange(location: 0, length: placeholderAttributedString.length))
    searchField.attributedPlaceholder = placeholderAttributedString

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

Единственный приемлемый ответ на данный момент, я использую Xcode 11.0

Sachintha Udara 07.10.2019 11:20

Попробуйте стереть все содержимое и настройки на симуляторе :)

Chathuranga Silva 29.10.2019 13:17

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

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

    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
}

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

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

Свифт 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, измените метод ниже. Очистите и создайте, если проблема не устранена.

Цель С

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

}

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

Цель С

[textField setAttributedPlaceholder:[[NSAttributedString alloc] initWithString:@"PlaceHolder Text" attributes:@{NSForegroundColorAttributeName:[UIColor whiteColor]}]];

В Свифт 5

txtTitle.attributedPlaceholder = NSAttributedString(string:"PlaceHolder Text", attributes: [NSAttributedString.Key.foregroundColor: UIColor.white])

Я думаю, что это ошибка со стороны XCode, и, надеюсь, они исправят ее в следующем выпуске. Вы можете быстро исправить это, удалив все содержимое и настройки на устройстве симулятора.

Я удалил var "_placeholderLabel" в разделе "Определяемые пользователем атрибуты времени выполнения"

Удалите подчеркивание "_" и попробуйте это.

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

Должно работать на всех версиях!

Это сработало для меня в симуляторе и Xcode 11.2.1. Спасибо

srinadh 05.12.2019 23:16

Да, эта проблема связана с версией Xcode. У меня есть Xcode 11.2.1, и я столкнулся с той же проблемой.

_placeholderLabel.textColor

если вы используете его из раскадровки как переменную времени выполнения и получаете проблему, просто удалите «_»

как это

после удаления "_" runtime Var начинает работать

Просто замените _placeholderLabel на placeholderLabel

Удалите "_" из формы "_placeholderLabel.textColor", попробуйте с "placeholderLabel.textColor".

Другие вопросы по теме