А в ваших iOS приложениях IBOutlet уже private?

    image

    Вы наверняка использовали Storyboard или XIB для верстки интерфейсов? Верстать из кода это прекрасно, но иногда намного проще понять как устроен какой-то из компонентов интерфейса, увидев его, а не прочитав. В этой записи я хочу обсудить необходимость использования для IBOutlet модификатора private.

    Разработчиков, для которых инкапсуляция IBOutlet является очевидной, тут вряд ли что-то удивит, зато может быть интересен опрос в конце статьи.

    Представим, что вы собираетесь создать IBOutlet (ссылку на View с Storyboard) для какого-нибудь из ваших UILabel. При перетаскивании мышкой Xcode заботливо создаст нам что-то вроде

    @IBOutlet weak var myLabel: UILabel!

    Я долгое время считал эту конструкцию оптимальной, до того момента как мой коллега не спросил — а почему твои IBOutlet не private?

    В самом деле, зачем мне оставлять все IBOutlet-ы доступными извне?
    Представим себе классическую задачу — у нас есть ячейка, в которой отображается, к примеру, чей-то контакт

    import UIKit
    
    class ContactCell: UITableViewCell {
    
        @IBOutlet private weak var nameLabel: UILabel!
        @IBOutlet private weak var positionLabel: UILabel!
    
        override func awakeFromNib() {
            super.awakeFromNib()
        }
    
        func setupCell(withContact contact: Contact) {
            nameLabel.text = contact.name
            positionLabel.text = contact.position
        }
    
    }

    С помощью добавления private к привычным нам IBOutlet можно гарантировать, что указанные поля ячейки не будет заданы из другого класса. Особенно это может быть полезно при командной работе, когда кто-то по неосторожности / нехватке времени / глупости (нужное подчеркнуть) попробует задать цвета, текст или какие-то другие свойства у Label-ов ячейки прямо в методе tableView(_:cellForRowAt:).

    А представьте, что ячейка или целый ViewController содержит множество IBOutlet-ов, что настроек отображения масса. Не проще ли обезопасить себя добавлением private, чем потом искать почему внешний вид элемента вдруг изменился или откуда-то появился Gesture Recognizer, который задает неожиданное поведение?

    P.S.: Если после прочтения вам захочется использовать private для IBOutlet-ов, то для простоты можно завести для этого снипет в Xcode.

    Ниже приведен опрос, если вы захотите прокомментировать свой вариант ответа, welcome в комментарии.

    Только зарегистрированные пользователи могут участвовать в опросе. Войдите, пожалуйста.

    А как вы в общем случае предпочитаете задавать IBOutlet?

    • 50,0%@IBOutlet private weak var someLabel: UILabel!53
    • 7,6%@IBOutlet weak private var someLabel: UILabel!8
    • 14,2%@IBOutlet private weak var someLabel: UILabel?15
    • 0,9%@IBOutlet weak private var someLabel: UILabel?1
    • 3,8%@IBOutlet private var someLabel: UILabel?4
    • 8,5%@IBOutlet private var someLabel: UILabel!9
    • 15,1%никаких IBOutlet, интерфейс 100% задается из кода16

    Комментарии 10

      0
      Ой как много воды о том, что такое инкапсуляция (что аутлеты не должны торчать наружу)… И, кстати говоря, это зависит от применяемой архитектуры, иногда нужно как раз наоборот. Но если «по-простому» — то да, в большинстве случаев аутлеты, если уж вы их используете, делаем приватными, чтобы извне был доступен минимум информации. Все, вся статья в двух предложениях.
        0
        Во многих проектах, с которыми я сталкивался, аутлеты как раз «торчали наружу», помимо этого Xcode при создании аутлетов не предлагает быстро добавить private, поэтому я думаю, что пояснения будут не лишними, особенно для начинающих.

        image
        +1
        В опросе нет вариантов без «private», но с «weak».
          0
          возможно, действительно имело смысл добавить еще несколько вариантов в том числе варианты без private — просто получалось очень массивно. а вы за вариант без private?
            0
            После прочтения Вашей статьи засомневался, но доселе использовал просто «weak var».
          +1

          Также и weak не нужен, и местами даже опасен.

            0
            А можете рассказать поподробнее?
              +2

              Типичная ситуация, захотел вдруг кодом изъять вьюшку, а потом вставить куда-либо снова.
              Разработчик пишет self.myView.removeFromSuperview(), и в этот момент вьюшка деаллоцируется, так ссылка держалась только иерархией вью, а не самим контроллером из-за weak, и далее так как у нас еще и IUO, то при обращунии без ? будет креш.
              Мало уже кто помнит, зачем давным давно писали weak в аутлетах ))).

            0

            -

              0
              Я использую всегда (ну кроме отдельных случаев):
              @IBOutlet private var someLabel: UILabel?

              с тех пор, как начал писать на свифте.
              Про weak уже сказали выше — он не нужен.
              Но почему так много людей делают аутлеты не опшионалами?
              Ведь в теории, при передаче в контроллер какого-то параметра (из segue например и особенно когда они не приватны) аутлеты могут быть ещё не привязаны и не доступны?
              Что это? Авось и так прокатит?

              Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

              Самое читаемое