Почему IBOutlets являются необязательными после быстрой миграции 5

После переноса проекта на 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)
]

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


person Jay    schedule 29.03.2019    source источник
comment
вы можете взглянуть на это: stackoverflow.com/a/40455613/2231118   -  person bpolat    schedule 29.03.2019
comment
@bpolat Я видел это раньше, но этого не было ни с одной предыдущей миграцией. Поскольку IBOutlets являются неявно развернутыми необязательными параметрами, у меня не должно возникнуть проблем с размещением их ссылок внутри массива. Так что я не уверен, что это ошибка компилятора или что...   -  person Jay    schedule 29.03.2019
comment
такого не было ни с одной предыдущей миграцией. Пожалуйста, покажите точную версию Xcode и точный код. Я могу перепроверить некоторые версии для вас. И определенно это не ошибка компилятора, и вам нужно изменить свой код.   -  person OOPer    schedule 30.03.2019
comment
Я добавил код @OOPer   -  person Jay    schedule 01.04.2019
comment
Извините извините. Мой удаленный комментарий был ошибкой, и я забыл преобразовать проект для использования Swift 5, и вы попали в крайний случай, когда только Swift 5 показывает другое поведение. Все, что сказал, я повторяю, что это не ошибка компилятора. Проверьте SE-0054 и SE-0140.   -  person OOPer    schedule 01.04.2019
comment
У меня те же проблемы (переход на Swift 5 с Swift 4) с XCode 10.2.   -  person Klinki    schedule 02.04.2019
comment
У меня есть аналогичный проект. SE-0054 говорит, что это было реализовано в Swift 4.2, однако я не получаю такого предупреждения ни в одном из проектов, использующих Swift 4.2, это происходит только после перехода на Swift 5.0.   -  person AdamM    schedule 03.04.2019


Ответы (1)


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

  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?' любому'

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

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

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

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

    let foo: UIButton = button
    

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

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

person Rob    schedule 30.03.2019
comment
Я добавил редактирование, которое показывает 2 примера того, где это происходит. - person Jay; 01.04.2019
comment
Каково идеальное решение для устранения этого предупреждения. Принудительное развертывание или приведение к Any не кажутся особенно чистыми решениями. - person AdamM; 03.04.2019
comment
В случае с IBOutlet (который в любом случае неявно распаковывается) лично я бы просто использовал оператор принудительной распаковки !. - person Rob; 03.04.2019
comment
Какой тогда смысл иметь UIButton! в качестве типа? кажется, теперь нет разницы между UIButton? и UIButton!. Я бы ожидал, что с foo: Any = button, где тип кнопки UIButton!, тип foo будет UIButton, а не необязательным... - person Jonathan.; 10.09.2019
comment
В чем смысл? Что ж, вам по-прежнему нравится поведение неявной развертки там, где это однозначно (например, button.backgroundColor = ...). Вот только проблема с Any, где непонятно. Подводя итог, не думайте больше о ! опционах как о «типе»: «Ментальная модель, которую многие люди используют для неявно развернутых опционалов, состоит в том, что они представляют собой тип, отличный от обычных опционалов. ... Новая ментальная модель для IUO - это та, в которой вы считаете ! синонимом ? с добавлением того, что он добавляет флаг в объявление, сообщая компилятору, что объявленное значение может быть неявно развернуто ». - person Rob; 10.09.2019