Swift @IBInspectables с приоритетом выбирают порядок выполнения

Я немного играю с @IBInspectables. Я создал многоразовое пользовательское представление, в котором есть несколько @IBInspectables.

Нет ли способа отдать приоритет @IBInspectables для выполнения?

В следующем случае для изменения цвета или шрифта заполнителя необходимо сделать это с помощью атрибутированного текста. Поэтому мне нужно, чтобы некоторые @IBInspectables, такие как Font, Color, выполнялись до @IBInspectable, который устанавливает текст-заполнитель.

В этом случае я сделал обходной путь, чтобы всегда получать цвет заполнителя. Тем не менее, я хочу добавить больше атрибутов в заполнитель, например шрифт, но если я не знаю, в каком порядке они будут выполняться, мне придется установить «attributedPlaceholder» из каждого IBInspectable, который изменяет заполнитель)

@IBInspectable
var placeholder: String? {
    didSet {
        guard let placeholder = placeholder else { return }

        textField.attributedPlaceholder = NSAttributedString(string: placeholder, attributes: [NSAttributedStringKey.foregroundColor: placeholderColor ?? UIColor.red])
    }
}

@IBInspectable
var placeholderColor: UIColor? {
    didSet {
        guard let placeholderColor = placeholderColor else { return }

        textField.attributedPlaceholder = NSAttributedString(string: textField.placeholder != nil ? textField.placeholder! : "", attributes: [NSAttributedStringKey.foregroundColor: placeholderColor])
    }
}

person Pablo Sanchez Gomez    schedule 20.03.2018    source источник
comment
Я так не думаю, но, возможно, если бы вы более конкретно указали на актуальную проблему, это могло бы иметь значение. @IBInspectable аналогичен раскрытию свойства в Interface Builder — что-то, что раньше было похоже на установку свойства для элемента управления в Visual Basic. Настоящий вопрос для вас: почему? Зачем кому-то заботиться о приоритете String над UIColor в режиме разработки? Без такой ясности я предполагаю, что либо не понимаю реальной проблемы, либо ответ отрицательный.   -  person dfd    schedule 20.03.2018
comment
Чтобы установить цвет заполнителя текстового поля, мне нужно сделать это через атрибут String, потому что они не позволяют вам напрямую изменять цвет заполнителя. Итак, в примере, который я написал, я должен сделать обходной путь, потому что, если я просто напишу textField.placeholder = placeholder, он не установит цвет, если цвет заполнителя будет выполнен раньше. Кроме того, я хочу добавить собственный шрифт в заполнитель через IBInspectable, и мне нужно писать так или иначе, в зависимости от того, что будет выполнено раньше.   -  person Pablo Sanchez Gomez    schedule 20.03.2018
comment
Ok. Во-первых, я не могу удалить свой голос против без редактирования. Я бы - и буду - но, может быть, вам следует добавить немного этой детали к вашему вопросу. (И я извиняюсь за это.) Во-вторых, я не думаю, что это поможет вам - я все еще не думаю, что вы можете устанавливать приоритеты для отдельных свойств для инструмента времени разработки - но проверьте, функциональность в prepareForInterfaceBuilder(), переопределение в UIView может выполнить что-то близкое к тому, что вы пытаетесь сделать.   -  person dfd    schedule 20.03.2018
comment
Не беспокойтесь, увидев ваш ответ, я уже редактировал вопрос, потому что я очень плохо объяснил себя :(. Может быть, я проверю, если в какой-то момент жизни UIView все они загружены, и я установлю атрибутированную строку (Чтобы проверить функциональность, я также могу скомпилировать приложение, но оно создает неожиданное поведение, потому что, если они выполняются в разных потоках, это гонка) Перед публикацией вопроса я провел несколько тестов, и в некоторых представлениях placeHolder выполняется раньше чем цвет и наоборот.   -  person Pablo Sanchez Gomez    schedule 20.03.2018
comment
У @Sulthan есть очень хороший ответ. И последнее замечание - ...если они выполняются в разных потоках... - я могу что-то неправильно понимать, но если вы говорите об изменении пользовательского интерфейса, они все относятся к основному потоку.   -  person dfd    schedule 20.03.2018
comment
Да, это правда, но поскольку 2 экземпляра одного и того же класса с одинаковыми ключами и значениями выполняются в разном порядке, я подумал, что, возможно, есть что-то асинхронное в вызове @IBInspectable или во время их обнаружения или что-л.   -  person Pablo Sanchez Gomez    schedule 23.03.2018


Ответы (1)


Вы должны написать сеттеры таким образом, чтобы порядок вызовов не имел значения. Это относится не только к порядку вызовов в Interface Builder, но и к порядку при программном вызове.

Не имеет значения, звоните ли вы:

view.placeholder = 
view.placeholderColor = 

or

view.placeholderColor = 
view.placeholder = 

Пример реализации:

@IBInspectable
var placeholder: String? {
   didSet {
      updatePlaceholder()
   }
}

@IBInspectable
var placeholderColor: UIColor? {
   didSet {
      updatePlaceholder()
   }
}

private func updatePlaceholder() {
   textField.attributedPlaceholder = NSAttributedString(
       string: placeholder ?? "",
       attributes: [.foregroundColor: placeholderColor ?? UIColor.red]
   )
}
person Sulthan    schedule 20.03.2018
comment
Спасибо, я не знаю, как я не подумал об этом! :). Я также добавил защиту let placeholder = placeholder, let placeholderColor = placeholderColor else { return }, чтобы textField.attributedPlaceholder не выполнялся более одного раза, а также я хочу, чтобы в @IBInspectables были обязательные значения :) - person Pablo Sanchez Gomez; 23.03.2018