Why are IBOutlets optionals after swift 5 migration

白昼怎懂夜的黑 提交于 2019-12-31 16:37:27

问题


After migrating the project to swift 5, I'm getting a lot of errors such as

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

I'm not sure what's causing this. One example where this is happening(there are a bunch) is when I'm setting the view.accessibilityElements. The array is supposed to contain : [Any]?... Any idea what's causing this?

Here is an example:

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

view.accessibilityElements = [shareButton, shareTitleLabel]

Here is another example:

@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)
]

When setting the elements above like this, it causes the mentioned error


回答1:


A couple of observations:

  1. It’s actually not the migration, itself, that is causing the issue. The issue is simply that you’re now compiling it Swift 5, which now warns you about the ambiguous coercion.

    Since you didn’t share the precise code that produced this warning, consider this example that produces that warning:

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

    So, glancing at this code, is foo the optional or is it the unwrapped value? In Swift 5, it brings this ambiguity to our attention with this warning

    warning: expression implicitly coerced from 'UIButton?' to 'Any'

    And it will show you three possible auto-fixes to eliminate this ambiguity, namely either:

    • use nil-coalescing operator, ??;
    • force unwrap it, !; or
    • just cast it with as Any to explicitly say that foo will be the optional with no unwrapping.
       

    Bottom line, we want to be able to easily reason about our code, and the Any type just makes this ambiguous. The compiler no longer makes assumptions as to whether you wanted the button to be unwrapped or not and is asking us to make our intentions explicit.

  2. For sake of comparison, consider the following two scenarios, where there is no ambiguity, and thus no warning. For example, considering the same implicitly unwrapped optional, here it knows that the implicit unwrapping should take place:

    let foo: UIButton = button
    

    Whereas here it knows that foo will be the optional:

    let foo: UIButton? = button
    
  3. If you’re wondering why your implicitly unwrapped UIButton! outlet is being treated as UIButton? at all (rather than as an ImplicitlyUnwrappedOptional type or just automatically force unwrapping it even though you’re using Any type), there are interesting discussions related to that in Reimplementation of Implicitly Unwrapped Optionals and the SE-0054 Abolish ImplicitlyUnwrappedOptional type.



来源:https://stackoverflow.com/questions/55422914/why-are-iboutlets-optionals-after-swift-5-migration

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!