在不创建新常量的情况下将可选值解包到保护条件中的预定义变量

Unwrapping optionals to a pre-defined variable in the guard condition without creating a new constant

Swift guard 语句允许您将可选值解包为一个新常量,并在赋值失败时尽早 return。

var someString:String? = "hello"
...
...  
guard let newString = someString 
   else {
     return
   }

...

如果我想解包一个可选变量并将其设置为预定义的非可选变量,我首先解包为新常量 (newString),然后在 guard 语句之后设置非可选变量像这样:

var someString:String? = "hello"
var nonOptionalString:String = "bonjour"
...
...
guard let newString = someString 
   else {
     return
   }
nonOptionalString = newString

...

有没有办法在不创建新常量的情况下在 guard 语句的条件下设置一个预定义的、非可选的 var? 像下面这样的东西(它不不工作)?

var someString:String? = "hello"
var nonOptionalString:String = "bonjour"
...
...
guard nonOptionalString = someString 
   else {
     return
   }
...

如果这样的事情不可能,Swift 语言设计或技术原因背后是否存在关于为什么这不存在的基本哲学?

如果重点是只在赋值可能的情况下进行赋值,写:

nonOptionalString = someString ?? nonOptionalString

如果你真的需要return如果赋值是不可能的,那么就写一个if/else子句:

if someString != nil {
    nonOptionalString = someString!
} else {
    return
}

换句话说,别再花哨了,说出你的意思。

我有两种方法可以做到这一点。

  1. guard let someString = someString else { return }

这只是检查具有相同变量名称的值。

  1. guard someString != nil else { return }

做第二个,你甚至可以用一声巨响 (!) 声明它在某种程度上是 "pre-defined" 到 "non-optional"。

所以现在你可以像这样声明它:

var someString:String! = "hello"

我想你正在寻找这个。

编辑:现在您可以使用自己的示例了。

guard someString != nil, nonOptional == someString else { return }

我只会测试 nil,然后在我知道它不是时强制解包:

var someString: String? = "hello"
let nonOptionalString: String       // note, you don't have to initialize this with some bogus value

guard someString != nil else { return }
nonOptionalString = someString!

或者如果 someString 是某个方法或闭包的参数,您可以使用相同的变量名在 guard 语句中展开,进一步简化生活:

func foo(someString: String?) {
    guard let someString = someString else { return }

    // now I can just use local `someString`, which is not optional anymore
}

如果你急于在一条语句中解包并退出-if-nil,理论上你可以编写一个函数来解包,如果可以的话,或者如果不能则抛出错误:

extension Optional {
    enum OptionalError: Error {
        case unwrapFailed
    }

    func unwrap<T>() throws -> T {
        if self == nil { throw OptionalError.unwrapFailed }
        return self as! T
    }
}

那么你可以这样做:

do {
    firstNonOptional  = try firstOptional.unwrap()
    secondNonOptional = try secondOptional.unwrap()
    thirdNonOptional  = try thirdOptional.unwrap()
} catch {
    return
}

我认为这是可怕的矫枉过正,但如果您迫切希望每次展开都将其提炼成一行,这是一种方法。