Принудительно разверните или используйте дополнительную цепочку для установки свойства

Учитывая необязательный var pinImageView: UIImageView?, у которого есть установленные свойства, я не уверен, какой способ предпочтительнее установить свойство. Например:

if let image = UIImage(named: "Pin") {
    pinImageView = UIImageView(image: image)
    pinImageView?.restorationIdentifier = "pin"
}

or

if let image = UIImage(named: "Pin") {
    pinImageView = UIImageView(image: image)
    pinImageView!.restorationIdentifier = "pin"
}

person bhartsb    schedule 15.07.2018    source источник
comment
Ответ на вопрос что предпочтительнее может основываться на мнении, когда нет общепринятого способа. Этот сайт кажется неподходящим для сбора таких мнений.   -  person OOPer    schedule 15.07.2018
comment
Принудительно разворачивать (!) всегда не рекомендуется, так как это может привести к сбою вашего приложения. В приведенном выше примере, хотя pinImageView инициализируется непосредственно перед использованием принудительной развертки (!) на нем, и он будет работать, как и ожидалось, с обоими подходами выше, но все же я бы рекомендовал первый подход. Избегайте привыкания к проблемному подходу.   -  person Kamran    schedule 15.07.2018
comment
@OOPer Откуда мне знать заранее, что этот вопрос основан на мнении? Один из способов можно считать неправильным.   -  person bhartsb    schedule 15.07.2018
comment
Может быть, когда ваш вопрос будет закрыт.   -  person OOPer    schedule 15.07.2018
comment
Есть и третий вариант:if let image = UIImage(named: "Pin"), let view = UIImageView(image: image) { view.restorationIdentifier = "pin" }   -  person NRitH    schedule 15.07.2018
comment
Я бы использовал локальную необязательную переменную   -  person Sulthan    schedule 15.07.2018
comment
@Kamran ! не обескуражен. У него есть законные варианты использования. Иногда вы просто не можете справиться с делом по-другому. Не стоит заявлять, что ваше приложение не рухнет, а вместо этого создаст неопределенное поведение приложения. Кроме того, я часто вижу, как люди избегают !, но все же добавляют fatalError() по всему коду.   -  person Sulthan    schedule 15.07.2018


Ответы (2)


какой путь предпочтительнее

Общепринято, что вам следует избегать ! (принудительное развертывание), которое просто напрашивается на сбой, поэтому этого использования следует избегать:

if let image = UIImage(named: "Pin") {
    pinImageView = UIImageView(image: image)
    pinImageView!.restorationIdentifier = "pin"
}

В этом случае, поскольку вы только что присвоили pinImageView, принудительная распаковка безопасна, но она по-прежнему вызывает тревогу у вас или любого другого, кто будет читать ваш код в будущем. "Тьфу, они используют принудительную развертку здесь. Может ли это произойти сбой? Ну, может ли pinImageView быть nil? Нет, это было просто назначено в предыдущей строке, так что все в порядке." Зачем подвергать себя и других этому мыслительному процессу; по возможности избегайте !.

Это использование:

if let image = UIImage(named: "Pin") {
    pinImageView = UIImageView(image: image)
    pinImageView?.restorationIdentifier = "pin"
}

безопаснее, потому что он использует необязательную цепочку для развертывания pinImageView и избегает оператора сбоя !, но по-прежнему разворачивает необязательную переменную.

Третий вариант:

Причина, по которой imageView является необязательным, заключается в том, что вы присвоили его необязательной переменной. Если вместо этого вы используете константу let для хранения объекта во время его настройки, вы можете избежать заполнения своего кода кодом распаковки:

if let image = UIImage(named: "Pin") {
    let imageView = UIImageView(image: image)
    imageView.restorationIdentifier = "pin"
    pinImageView = imageView
}

Этот метод хорошо работает, когда вы назначаете много свойств объекту, так как вы можете избежать множества операций развертывания.

Не беспокойтесь о лишней строке кода. Компилятор оптимизирует это. Код для удобочитаемости и ясности.

person vacawama    schedule 15.07.2018
comment
Вы бы сказали, что второй необязательный способ цепочки подходит, когда назначается только одно свойство? - person bhartsb; 16.07.2018
comment
@bhartsb, все в порядке. Я бы, вероятно, сделал это, назначив только одно свойство. Но к тому времени, когда вы назначаете два или три, необязательная цепочка начинает выделяться. - person vacawama; 16.07.2018

У нас в команде есть правило стиля/проверки кода, которое гласит: «Нельзя использовать оператор ! без комментария, описывающего, почему это безопасно».

Потому что ! уничтожает все преимущества нулевой безопасности в Swift, а случайное его использование вызывает сбои и тащит язык обратно в ад C/C++/Java/C#/Javascript/etc NullPointerException.

Так что в вашем случае

pinImageView?.restorationIdentifier = "pin"

вариант определенно предпочтительнее.

person Jon N    schedule 15.07.2018
comment
Спасибо, я был на заборе о решении принять. - person bhartsb; 16.07.2018