【问题标题】:Swift: Comparing Implicitly Unwrapped Optionals results in "unexpectedly found nil while unwrapping an Optional values"Swift:比较隐式展开的选项会导致“在展开选项值时意外发现 nil”
【发布时间】:2015-09-21 18:05:09
【问题描述】:

如果得到这个类并想根据值比较它的实例

class LocationOption: NSObject {
  var name:String!
  var radius:Int!
  var value:String!

  override func isEqual(object: AnyObject?) -> Bool {
    if let otherOption = object as? LocationOption {
        return (self.name == otherOption.name) &&
            (self.radius == otherOption.radius) &&
            (self.value == otherOption.value)
    }
    return false
  }
}

执行时:

var a = LocationOption()
var b = LocationOption()

a.name = "test"
b.name = "test"

if a == b {  // Crashes here!!
  print("a and b are the same");
}

这会因“在展开可选值时意外发现 nil”而崩溃?您可以将所有这些复制到 Playground 中进行复制。

这似乎是由于Implicitly Unwrapped Optionals。如果我将所有字段声明为 Optionals,它将按预期工作。

但就我而言,我希望将这些属性设为Implicitly Unwrapped Optionals。我应该如何写 isEqual?

===

更新:@matt 是对的,因为我不想更改为“常规”选项,所以我最终得到了这个:

class LocationOption: Equatable {
    var name:String!
    var requireGps:Bool!
    var radius:Int!
    var value:String!
}

func ==(lhs: LocationOption, rhs: LocationOption) -> Bool {
    let ln:String? = lhs.name as String?, rn = rhs.name  as String?
    let lr = lhs.radius as Int?, rr = rhs.radius as Int?
    return ln == rn && lr == rr
}

【问题讨论】:

    标签: ios swift swift2 ios9


    【解决方案1】:

    您无法打开 nil。那就是法律。你不能仅仅通过使用隐式展开的 Optionals 来绕过这个定律。您隐式展开的选项仍然是选项。因此,当您的测试引用 self.radiusself.value 而您没有设置它们时,它们为零。所以你试图打开 nil 并且你崩溃了。

    事实上,你使用 if 隐式展开 Optionals 会使事情变得更糟。当您将它们声明为普通 Optionals 时,它们不会被隐式解包,因此它们根本不会被解包 - 将普通 Optionals 与 == 运算符进行比较是安全的,因为编译器会为您插入 nil 测试。因此,法律永远不会被违反。但是您通过使这些隐式展开的 Optional 丢弃了这种安全性。 这就是感叹号的意思;这意味着您可能会崩溃。如果您不希望这种情况发生,那么:

    • 不要那样做。或者:

    • 您自己为nil 插入一个显式测试。

    【讨论】:

    • 您的权利。由于我不想更改为普通的 Optionals,所以我最终得到了这个:class LocationOption: Equatable { var name:String! var requireGps:布尔!变量半径:整数!变量值:字符串! } func ==(lhs: LocationOption, rhs: LocationOption) -> Bool { let ln:String? = lhs.name 作为字符串?, rn = rhs.name 作为字符串?让 lr = lhs.radius 作为 Int?, rr = rhs.radius 作为 Int?返回 ln == rn && lr == rr }`
    • 我想你会发现你并没有覆盖你所有的基础。在这里使用普通的 Optionals 真的会好得多...
    猜你喜欢
    • 1970-01-01
    • 2020-12-28
    • 1970-01-01
    • 2018-09-22
    • 2015-10-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多