Значение набора @IBInspectable в раскадровке не распространяется на код - PullRequest
0 голосов
/ 23 мая 2018

Без опыта работы с iOS меня попросили обновить до Swift 4 приложение, использующее Swift 3. Я обновил язык для использования в «языковой версии Swift» и следовал рекомендациям, сделанным xCode (явно используйте @objc).

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

Значение этой переменной правильно установлено в MainStoryboard, но когда создается экземпляр класса, это значение не устанавливаетсяк значению в раскадровке, и в результате пользовательское текстовое поле не ведет себя так, как должно.В журнале не упоминается ни одной ошибки.

Кто-нибудь сталкивался с такой же проблемой?

Я проверил раскадровку и класс, не обнаружил никаких проблем, я также сравнил код версии со Swift3 и тот, который я обновил со Swift 4, и нет никаких отличий (кроме @objc).

Есть ли что-то еще, что может помочь мне выяснить, почему значение, установленное в MainStoryboard, не распространяется на класс?

Редактировать

Ниже приведен код, связанный с проблемой:

  • объявлена ​​переменная isPassword, отражающая значение переменной IBInspectable
  • объявлена ​​переменная IBInspectable
  • , когда awakeFromNib в зависимости от значения isPassword, вызывается метод скрытия текста или нет

    @IBDesignable class CustomEditText: UITextField {
    var isPassword = false
    
    // Inspector variable determining if the text must be hidden or not
    @IBInspectable var isAPasswordField: Bool {
        get{
            return self.isPassword
        }
    
        set{
            self.isPassword = isAPasswordField
        }
    }
    
    override init(frame: CGRect) {
        super.init(frame: frame)
        setup()
    }
    
    required init(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)!
        setup()   // Set borders, font, ...
    }
    
    override func awakeFromNib() {
        super.awakeFromNib()
        if isPassword {               // isPassword does not reflect the value of isAPasswordField set in storyboard
            self.isSecureTextEntry = true
            setRevealButton()         // the text is hidden
        } else {
            setCustomClearButton()    // the text is not hidden
        }
    }
    

...

Ответ

@ Алладиниан дал хороший ответ.Ниже для полноты еще одно решение, которое я нашел:

@IBInspectable var isPasswordField: Bool = false {
    didSet{
        self.isPassword = isPasswordField

        if isPassword {
            self.isSecureTextEntry = true
            setRevealButton()
        } else {
            setCustomClearButton()
        }
    }
}

Ответы [ 2 ]

0 голосов
/ 07 июня 2019

Следующий код прекрасно работает для новых версий:

@IBInspectable var isAPass: Bool {
    get {
        return self.isSecureTextEntry
    }

    set {
        self.isSecureTextEntry = newValue
    }
}
0 голосов
/ 23 мая 2018

Правильная форма будет (обратите внимание на назначение сеттера):

@IBInspectable var isAPasswordField: Bool {
    get {
        return self.isPassword
    }

    set {
        self.isPassword = newValue
    }
}

, поскольку фактическое значение не было установлено ( и не будет - по крайней мере, "напрямую")на isAPasswordField (помните, мы все-таки реализуем установщик вычисляемого свойства ...)

Кроме того, почему бы вам просто не использовать isPassword напрямую, пометив его как проверяемый, избегая необходимостидля дополнительного ivar?


PS: newValue - это имя по умолчанию для устанавливаемого значения.Подробнее об этом вы можете прочитать в разделе Объявление стенографического набора в книге по языку программирования Swift

...