Почему IBOutlets опциональны после быстрой миграции 5? - PullRequest
5 голосов
/ 29 марта 2019

После переноса проекта в swift 5 я получаю много ошибок, таких как

Expression implicitly coerced from 'UIButton?' to 'Any'

Я не уверен, что является причиной этого.Один пример, где это происходит (есть куча), когда я устанавливаю view.accessibilityElements.Массив должен содержать: [Any]? ... Есть идеи, что это вызывает?

Вот пример:

@IBOutlet weak var shareButton: UIButton!
@IBOutlet weak var shareTitleLabel: UILabel!

view.accessibilityElements = [shareButton, shareTitleLabel]

Вот еще один пример:

@IBOutlet weak var titleLabel: UILabel!

let titleConstraints = [
        NSLayoutConstraint(item: titleLabel, attribute: .leading, relatedBy: .equal, toItem: otherView, attribute: .leading, multiplier: 1, constant: horizontalTextInset),
        NSLayoutConstraint(item: titleLabel, attribute: .trailing, relatedBy: .equal, toItem: otherView, attribute: .trailing, multiplier: 1, constant: -horizontalTextInset)
]

При установке вышеуказанных элементов это вызывает указанную ошибку

1 Ответ

4 голосов
/ 30 марта 2019

Пара наблюдений:

  1. На самом деле проблема не в самой миграции. Проблема в том, что вы сейчас компилируете Swift 5, которая теперь предупреждает вас о неоднозначном принуждении.

    Поскольку вы не указали точный код, который выдал это предупреждение, рассмотрите пример, который выдает это предупреждение:

    class ViewController: UIViewController {
    
        @IBOutlet var button: UIButton!
    
        override func viewDidLoad() {
            super.viewDidLoad()
    
            let foo: Any = button
            print(type(of: foo))
    
            // do something with `foo`
        }
    }
    

    Итак, взглянув на этот код, foo является необязательным или это развернутое значение? В Swift 5 это двусмысленность обращает наше внимание на это предупреждение

    предупреждение: выражение неявно приведено из 'UIButton?' на «Любой»

    И он покажет вам три возможных авто-исправления, чтобы устранить эту двусмысленность, а именно:

    • использовать nil оператор коалесцирования, ??;
    • принудительно разверните его, !; или
    • просто приведите его с помощью as Any, чтобы явно сказать, что foo будет необязательным без развертывания.

    Суть в том, что мы хотим легко рассуждать о нашем коде, а тип Any просто делает это неоднозначным. Компилятор больше не делает предположений относительно того, хотите ли вы, чтобы button был развернут или нет, и просит нас сделать наши намерения явными.

  2. Для сравнения рассмотрим следующие два сценария, в которых нет двусмысленности и, следовательно, нет предупреждения. Например, рассматривая то же самое неявно развернутый необязательный, здесь он знает, что неявное развертывание должно иметь место:

    let foo: UIButton = button
    

    Тогда как здесь известно, что foo будет необязательным:

    let foo: UIButton? = button
    
  3. Если вам интересно, почему ваша неявно развернутая розетка UIButton! вообще обрабатывается как UIButton? (а не как ImplicitlyUnwrappedOptional, или просто автоматически принудительно распаковывает ее, даже если вы используете Any тип), есть интересные дискуссии, связанные с тем, что в переопределение неявно развернутых необязательных опций и SE-0054 отмените ImplicitlyUnwrappedOptional тип .

...