Swift:测试nil的选项

tng*_*tng 125 optional ios swift

我正在使用Xcode 6 Beta 4.我有这种奇怪的情况,我无法弄清楚如何适当地测试选项.

如果我有一个可选的xyz,是正确的测试方法:

if (xyz) // Do something
Run Code Online (Sandbox Code Playgroud)

要么

if (xyz != nil) // Do something
Run Code Online (Sandbox Code Playgroud)

文档说这是第一种方式,但我发现有时,第二种方式是必需的,并且不会产生编译器错误,但有时,第二种方式会产生编译器错误.

我的具体示例是使用桥接到swift的GData XML解析器:

let xml = GDataXMLDocument(
    XMLString: responseBody,
    options: 0,
    error: &xmlError);

if (xmlError != nil)
Run Code Online (Sandbox Code Playgroud)

在这里,如果我刚刚做了:

if xmlError
Run Code Online (Sandbox Code Playgroud)

它总会回归真实.但是,如果我这样做:

if (xmlError != nil)
Run Code Online (Sandbox Code Playgroud)

然后它工作(如在Objective-C中如何工作).

是否存在GData XML以及它对待我缺少的选项的方式?

ktz*_*ang 157

在Xcode Beta 5中,他们不再允许您这样做:

var xyz : NSString?

if xyz {
  // Do something using `xyz`.
}
Run Code Online (Sandbox Code Playgroud)

这会产生错误:

不符合协议'BooleanType.Protocol'

您必须使用以下形式之一:

if xyz != nil {
   // Do something using `xyz`.
}

if let xy = xyz {
   // Do something using `xy`.
}
Run Code Online (Sandbox Code Playgroud)

  • 有人可以详细说明为什么xyz == nil不起作用? (4认同)

gog*_*elj 22

要添加到其他答案,而不是在if条件内分配不同名称的变量:

var a: Int? = 5

if let b = a {
   // do something
}
Run Code Online (Sandbox Code Playgroud)

您可以重复使用相同的变量名称,如下所示:

var a: Int? = 5

if let a = a {
    // do something
}
Run Code Online (Sandbox Code Playgroud)

这可以帮助您避免用尽创意变量名称...

这利用了Swift支持的变量阴影.


Isa*_*man 18

使用可选项的最直接方法之一如下:

假设xyz是可选类型,Int?例如.

if let possXYZ = xyz {
    // do something with possXYZ (the unwrapped value of xyz)
} else {
    // do something now that we know xyz is .None
}
Run Code Online (Sandbox Code Playgroud)

这样,您既可以测试是否xyz包含值,如果包含值,则立即使用该值.

关于编译器错误,类型UInt8不是可选的(注意没有'?'),因此无法转换为nil.在将其视为一个变量之前,请确保您正在使用的变量是可选的.

  • 这是打开可选变量的标准方法和推荐方法."'如果让'"非常强大. (3认同)

Fan*_*ing 13

Swift 3.0,4.0

主要有两种方法可以检查nil的可选项.以下是它们之间进行比较的示例

如果让

if let是检查nil可选项的最基本方法.其他条件可以附加到此nil检查,以逗号分隔.对于下一个条件,变量不能为nil.如果只需要nil检查,请删除以下代码中的额外条件.

除此之外,如果x不是nil,if闭包将被执行并且x_val将在内部可用.否则触发else闭包.

if let x_val = x, x_val > 5 {
    //x_val available on this scope
} else {

}
Run Code Online (Sandbox Code Playgroud)

2.守卫让

guard let可以做类似的事情.它的主要目的是使其在逻辑上更合理.这就像说确保变量不是nil,否则停止该功能.guard let也可以做额外的条件检查if let.

不同之处在于,展开的值将guard let在与以下注释相同的范围内可用.这也导致在其他封闭,该程序必须退出当前的范围,由点return,break等等.

guard let x_val = x, x_val > 5 else {
    return
}
//x_val available on this scope
Run Code Online (Sandbox Code Playgroud)


cod*_*ter 10

来自swift编程指南

如果声明和强制解包

您可以使用if语句来确定可选项是否包含值.如果可选项具有值,则计算结果为true; 如果它根本没有值,则计算结果为false.

所以最好的方法是

// swift > 3
if xyz != nil {}
Run Code Online (Sandbox Code Playgroud)

如果您正在使用xyzin if语句.那么您可以xyz在常量变量中解包if语句.因此,您不需要在if语句中展开每个位置xyz.

if let yourConstant = xyz{
      //use youtConstant you do not need to unwrap `xyz`
}
Run Code Online (Sandbox Code Playgroud)

这个惯例是建议的apple,然后是devlopers.

  • 在Swift 3中你必须做`if xyz!= nil {...}`. (2认同)

Chr*_*ick 8

虽然你仍然必须明确比较一个可选的nil或使用可选的绑定来另外提取它的值(即选项不会隐式转换为布尔值),但值得注意的是,Swift 2添加了guard语句以帮助避免工作时的厄运金字塔有多个可选值.

换句话说,您的选项现在包括显式检查nil:

if xyz != nil {
    // Do something with xyz
}
Run Code Online (Sandbox Code Playgroud)

可选绑定:

if let xyz = xyz {
    // Do something with xyz
    // (Note that we can reuse the same variable name)
}
Run Code Online (Sandbox Code Playgroud)

guard语句:

guard let xyz = xyz else {
    // Handle failure and then exit this code block
    // e.g. by calling return, break, continue, or throw
    return
}

// Do something with xyz, which is now guaranteed to be non-nil
Run Code Online (Sandbox Code Playgroud)

请注意,当有多个可选值时,普通可选绑定如何导致更大的缩进:

if let abc = abc {
    if let xyz = xyz {
        // Do something with abc and xyz
    }        
}
Run Code Online (Sandbox Code Playgroud)

您可以使用guard语句来避免此嵌套:

guard let abc = abc else {
    // Handle failure and then exit this code block
    return
}

guard let xyz = xyz else {
    // Handle failure and then exit this code block
    return
}

// Do something with abc and xyz
Run Code Online (Sandbox Code Playgroud)


yoA*_*ex5 6

斯威夫特可选

除了if letguard let您可以使用的结构Nil-Coalescing Operator

如果可选值包含 value,则 ( ) 对其进行解包;如果是nil-coalescing operator,则返回默认值。表达式 a 始终是可选类型。表达式必须与存储在其中的类型匹配。a ?? baaabanilba

let value = optionalValue ?? defaultValue
Run Code Online (Sandbox Code Playgroud)

如果optionalValuenil,它会自动赋值给defaultValue


Bro*_*son 6

Swift 5 协议扩展

这是一种使用协议扩展的方法,以便您可以轻松内联可选的 nil 检查:

import Foundation

public extension Optional {

    var isNil: Bool {

        guard case Optional.none = self else {
            return false
        }

        return true

    }

    var isSome: Bool {

        return !self.isNil

    }

}
Run Code Online (Sandbox Code Playgroud)

用法

var myValue: String?

if myValue.isNil {
    // do something
}

if myValue.isSome {
    // do something
}
Run Code Online (Sandbox Code Playgroud)

  • 这可能是“pythonistas”的“swift”类比,他们试图使语言保持某种形式的Python纯度。我的看法是?我刚刚将你的代码提升到我的 Utils mixin 中。 (2认同)

Ben*_*man 5

一个没有特别提及的选项是使用 Swift 的忽略值语法:

if let _ = xyz {
    // something that should only happen if xyz is not nil
}
Run Code Online (Sandbox Code Playgroud)

我喜欢这个,因为nil在像 Swift 这样的现代语言中检查感觉不合适。我认为它感觉不合适的原因nil基本上是一个哨兵值。在现代编程中,我们几乎在所有其他地方都取消了哨兵,所以nil感觉也应该这样做。