2

Swift 守卫语句允许您将可选项解包为新常量,并在赋值失败时提前返回。

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

...

如果我想解开一个可选变量并将其设置为预定义的非可选变量,我首先解包到新常量(newString),然后在保护语句之后设置非可选变量,如下所示:

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

...

有没有办法在不创建新常量的情况下在保护语句的条件内设置一个预定义的、非可选的 var? 类似于以下内容(不起作用)?

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

如果这样的事情是不可能的,那么 Swift 语言设计背后是否有一个基本的哲学或技术原因来解释为什么这不存在?

4

3 回答 3

1

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

  1. guard let someString = someString else { return }

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

  1. guard someString != nil else { return }

做第二个,你甚至可以用 bang(!) 声明它,它会以某种方式“预定义”为“非可选”。

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

var someString:String! = "hello"

我想你正在寻找这个。

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

guard someString != nil, nonOptional == someString else { return }
于 2017-05-16T22:33:20.753 回答
1

当我知道它不是时,我会测试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
}

如果你不顾一切地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
}

我认为这太可怕了,但如果你不顾一切地想在每次展开时将它提炼成一行,那是一种方法。

于 2017-05-17T00:54:52.130 回答
0

如果重点是仅在可以分配的情况下进行分配,请编写:

nonOptionalString = someString ?? nonOptionalString

如果您确实需要returnif 赋值是不可能的,那么只需编写一个 if/else 子句:

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

换句话说,不要再那么花哨了,直接说出你的意思。

于 2017-05-16T22:28:44.270 回答