Вы наверняка использовали 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 в комментарии.
Комментарии (10)
debug45
30.09.2018 09:22+1В опросе нет вариантов без «private», но с «weak».
slutsker Автор
30.09.2018 09:37возможно, действительно имело смысл добавить еще несколько вариантов в том числе варианты без private — просто получалось очень массивно. а вы за вариант без private?
debug45
30.09.2018 09:42После прочтения Вашей статьи засомневался, но доселе использовал просто «weak var».
eugeneego
30.09.2018 10:14Также и
weak
не нужен, и местами даже опасен.slutsker Автор
30.09.2018 10:15А можете рассказать поподробнее?
eugeneego
30.09.2018 10:22+1Типичная ситуация, захотел вдруг кодом изъять вьюшку, а потом вставить куда-либо снова.
Разработчик пишетself.myView.removeFromSuperview()
, и в этот момент вьюшка деаллоцируется, так ссылка держалась только иерархией вью, а не самим контроллером из-заweak
, и далее так как у нас еще и IUO, то при обращунии без?
будет креш.
Мало уже кто помнит, зачем давным давно писалиweak
в аутлетах ))).
Stas_Telnov
01.10.2018 12:07Я использую всегда (ну кроме отдельных случаев):
@IBOutlet private var someLabel: UILabel?
с тех пор, как начал писать на свифте.
Про weak уже сказали выше — он не нужен.
Но почему так много людей делают аутлеты не опшионалами?
Ведь в теории, при передаче в контроллер какого-то параметра (из segue например и особенно когда они не приватны) аутлеты могут быть ещё не привязаны и не доступны?
Что это? Авось и так прокатит?
GDXRepo
Ой как много воды о том, что такое инкапсуляция (что аутлеты не должны торчать наружу)… И, кстати говоря, это зависит от применяемой архитектуры, иногда нужно как раз наоборот. Но если «по-простому» — то да, в большинстве случаев аутлеты, если уж вы их используете, делаем приватными, чтобы извне был доступен минимум информации. Все, вся статья в двух предложениях.
slutsker Автор
Во многих проектах, с которыми я сталкивался, аутлеты как раз «торчали наружу», помимо этого Xcode при создании аутлетов не предлагает быстро добавить private, поэтому я думаю, что пояснения будут не лишними, особенно для начинающих.