Требуется ли вызывать метод "awakeFromNib ()" при установке в Swift cornerRadius? - PullRequest
1 голос
/ 03 апреля 2019

Я получил этот кусок кода из онлайн-урока, в котором рассказывается, как правильно устанавливать углы.

Я комментирую метод awakeFromNib() и prepareForInterfaceBuilder() и запускаю симулятор, результаты те же: кнопка все равно показывает круглый угол без awakeFromNib().

@IBDesignable
class RoundedButton: UIButton {

    @IBInspectable var cornerRadius: CGFloat = 4.0 {
        didSet {
            self.layer.cornerRadius = cornerRadius
        }
    }

    override func awakeFromNib() {
        self.setUpView()
    }

    override func prepareForInterfaceBuilder() {
        super.prepareForInterfaceBuilder()
        self.setUpView()
    }

    func setUpView() {
        self.layer.cornerRadius = 3.0
    }

}

Мне интересно, почему я должен использовать awakeFromNib() и prepareForInterfaceBuilder(), когда я уже установил угловой радиус в наблюдателе?

1 Ответ

3 голосов
/ 03 апреля 2019

Вы спрашиваете:

Мне интересно, почему я должен использовать awakeFromNib() и prepareForInterfaceBuilder(), когда я уже установил угловой радиус в наблюдателе?

Проблема в том, что если вы добавили свою кнопку в сцену раскадровки и у вас вообще не было установлено свойство @IBInspectable. Радиус угла вашего слоя никогда не будет установлен на 3 (или 4), потому что наблюдатель вызывается, только если впоследствии изменяется после инициализации. Вы должны убедиться, что у вас нет пути выполнения, куда не вызывается наблюдатель (или, по крайней мере, обновить радиус угла слоя в зависимости от значения вашего свойства). Вам необходимо настроить свой угловой радиус одним из этих способов (или, как я расскажу ниже, в init).


Но что, если вы по какой-то причине программно создаете экземпляр кнопки? В этом случае ни awakeFromNib, ни prepareForInterfaceBuilder не будут вызваны!

Итак, я бы предложил сделать это в init. Это охватывает все сценарии:

@IBDesignable
class RoundedButton: UIButton {
    @IBInspectable var cornerRadius: CGFloat = 3.0 {
        didSet {
            layer.cornerRadius = cornerRadius
        }
    }

    override init(frame: CGRect = .zero) {
        super.init(frame: frame)
        setUpView()
    }

    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
        setUpView()
    }
}

private extension RoundedButton {
    func setUpView() {
        layer.cornerRadius = cornerRadius
    }
}

Я также не уверен, почему у вас было одно значение по умолчанию в объявлении var, а другое - в setUpView, поэтому у меня просто есть одно, чтобы избежать двусмысленности.


Кстати, другой подход - использовать вычисляемое свойство, которое получает его из layer. Это позволяет избежать любой возможной путаницы (например, вы программно изменяете layer.cornerRadius в другом месте, вы действительно хотите, чтобы это свойство cornerRadius возвращало старое сохраненное значение, а не то, что слой действительно использует)?

@IBDesignable
class RoundedButton: UIButton {
    @IBInspectable var cornerRadius: CGFloat {
        get { return layer.cornerRadius }
        set { layer.cornerRadius = newValue }
    }

    override init(frame: CGRect = .zero) {
        super.init(frame: frame)
        setUpView()
    }

    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
        setUpView()
    }
}

private extension RoundedButton {
    func setUpView() {
        cornerRadius = 4.0
    }
}

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...