【问题标题】:Swift 5: Binary operator '==' cannot be applied to operands of type 'AnyObject?' and 'UIView?'Swift 5:二元运算符“==”不能应用于“AnyObject?”类型的操作数和“UIView?”
【发布时间】:2019-08-14 20:27:35
【问题描述】:

我使用 Swift 5 并尝试测试 someView 的所有 NSLayoutContraints 是否与某些 otherView 相关:

@IBOutlet var someView: UIView!
@IBOutlet var otherView: UIView!

for constraint in someView.constraints {
    if (constraint.firstItem == otherView) {
        ...
    }
}

此代码失败并出现以下错误:

二元运算符“==”不能应用于类型的操作数 “任何物体?”和“UIView?”

关于 Swift 中的类型和运算符还有很多其他问题,但我仍然不明白为什么会出现这个错误以及如何解决它:

  • constraint.firstItem 的类型为 AnyObject?。所以它要么是nil,要么是AnyObject类型的对象
  • otherViewUIView! 类型,所以保证不是nil,对吗?

据我所知AnyObject 是所有类都隐式遵守的协议。因此,将任何对象与AnyObject? 进行比较应该不是问题,不是吗?

那么,为什么constraint.firstItem == otherView 不起作用,正确的解决方法是什么?

额外问题:为什么错误消息提到UIView?而不是UIView!

【问题讨论】:

标签: ios swift


【解决方案1】:

只需使用 === 代替 ==,即

if (constraint.firstItem === otherView) {
   ....   
}

===(::)

返回一个布尔值,指示两个引用是否指向同一个对象实例。

此运算符测试两个实例是否具有相同的标识,而不是相同的值。有关值相等,请参阅等于运算符 (==) 和 Equatable 协议。

【讨论】:

    【解决方案2】:

    您正在处理需要解包的 optionals,并且您正在尝试比较与 === 相比更好的对象,=== 测试两个引用是否指向同一个对象。

    我建议:

    func doSomething() {
        guard let otherView = otherView else { return }
        for constraint in someView.constraints {
            guard let firstItem = constraint.firstItem else { continue }
    
            if firstItem === otherView {
                // do something
            }
        }
    }
    

    注意:您可以使用=== 比较两个可选引用,但如果它们都是nil,它将返回true


    根据下面@MartinR 的讨论,您可以使用混合方法来避免两个值都是nil 的情况,只需解开第一个:

    func doSomething() {
        guard let otherView = otherView else { return }
        for constraint in someView.constraints {
            if constraint.firstItem === otherView {
                // do something
            }
        }
    }
    

    otherView 的类型是UIView!,所以保证不为零,对吧?

    不,不能保证不是nil。如果你在一个需要 UIView 的地方使用它,如果它是 nil,它只会崩溃。 隐式展开的可选(IUO)仍然是一个可选。它可以nil。 IUO 获得的唯一特殊待遇是您可以在需要非可选类型的地方使用它,Swift 会为您解包。

    【讨论】:

    • === 还可以比较可选对象引用。
    • @MartinR,好吧,看看那个!当然,如果他们都是nil,他们会比较相等,所以你可能不想要这样。
    • 当你删除你的答案时,我正要发表评论:) - otherView 是一个 IUO 出口,所以可以预期它不是零。我认为有多种有效的方法,例如一个混合的:预先打开 otherView,但不要打开 constraint.firstItem
    【解决方案3】:

    在 Obj-C 中它可以工作,因为 isEqual 在运行时被查找。 在 Swift 中,它在编译期间必须是一个具体的类型。

    for constraint in someView.constraints {
    
        if let view = constraint.firstItem as? UIView {
            if (view == otherView) {
                ...
            }
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2017-02-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多