本文介绍了为什么 IBOutlets 在 swift 5 迁移后是可选的的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

将项目迁移到 swift 5 后,我收到了很多错误,例如

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

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

我不确定是什么原因造成的.发生这种情况的一个例子(有一堆)是当我设置 view.accessibilityElements 时.该数组应该包含:[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?

这是一个例子:

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

像这样设置上面的元素时,会导致上述错误

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

推荐答案

几点意见:

  1. 实际上并不是迁移本身导致了问题.问题很简单,您现在正在编译 Swift 5,它现在会警告您有关模棱两可的强制转换.

  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`
    }
}

那么,看一下这段代码,foo 是可选的还是解包的值?在 Swift 5 中,它通过这个警告让我们注意到了这种歧义

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

警告:从UIButton?"隐式强制的表达式到任何"

它会向您展示三种可能的自动修复来消除这种歧义,即:

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

  • 使用nil-合并运算符,??;
  • 强制解开它,!;或
  • 只需将其与 as Any 一起转换即可明确说明 foo 将是可选的,无需解包.
     
  • 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.
     

最重要的是,我们希望能够轻松地对我们的代码进行推理,而 Any 类型只会使这一点变得模棱两可.编译器不再假设您是否希望 button 被展开,而是要求我们明确表达我们的意图.

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.

为了比较,请考虑以下两种情况,其中没有歧义,因此没有警告.例如,考虑相同的隐式解包可选,这里它知道隐式解包应该发生:

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

而这里它知道 foo 将是可选的:

Whereas here it knows that foo will be the optional:

let foo: UIButton? = button

  • 如果您想知道为什么您隐式解包的 UIButton! 出口被视为 UIButton?(而不是作为 ImplicitlyUnwrappedOptional 类型或即使您使用 Any 类型也只是自动强制展开它),在 隐式解包选项的重新实现SE-0054 废除 ImplicitlyUnwrappedOptional 类型.

  • 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.

    这篇关于为什么 IBOutlets 在 swift 5 迁移后是可选的的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

  • 08-14 09:25