6

有时我发现自己在编写这样的 swift 2 代码:

class Test {
    var optionalInt: Int?
    var nonOptionalInt: Int = 0
    func test() {
        if let i = optionalInt {
            nonOptionalInt = i
        }
        // do more stuff
    }
}

有问题的部分是:

if let i = optionalInt {
    nonOptionalInt = i
}

换句话说:如果 optionalInt 有一个值,则将其分配给变量 nonOptionalInt,否则什么也不做。

在 swift 2 中是否有一种等效的方法可以在优雅的单行中表达这一点,而无需使用 if let i 添加中间变量?

编辑

在考虑了第一个答案之后......

显然有一个等价的方式

if optionalInt != nil {
    nonOptionalInt = optionalInt!
}

三元运算符 ? : 不等效,因为它们可能会触发原始代码不会触发的 didSet(如果这是预期的副作用,则很好)

迄今为止最优雅的答案似乎是

nonOptionalInt = optionalInt ?? nonOptionalInt

它也可能触发像三元运算符一样的 didSet,因此不等效(如果这是有意的,也很好)。

我想我对苹果的愿望是

nonOptionalInt = optionalInt ?? 

或者

nonOptionalInt ??= optionalInt
4

3 回答 3

10

您正在寻找的是nil 合并运算符

在这种情况下,您会像这样使用它:

nonOptionalInt = optionalInt ?? nonOptionalInt

编辑

回复:您对问题的最后一次编辑:

我想我对苹果的愿望是这样的 nonOptionalInt ??= optionalInt

...为什么希望你能建造它?:)

我还没有考虑到足以决定我是否会为一般情况推荐这样的东西,但如果它对您的情况有帮助,您可以创建一个??=操作员来执行您的要求,如下所示:

infix operator ??= {}

func ??= <T>(inout lhs: T, rhs: T?) -> Void {
  guard let value = rhs else { return }
  lhs = value
}

然后,查看它的实际效果:

let optionalNil: String? = nil,
  optionalValue: String? = "optionalValue",
  implicitlyUnwrappedNil: String! = nil,
  implicitlyUnwrappedValue: String! = "implicitlyUnwrappedValue"
var a = "a", b = "b", c = "c", d = "d"

a ??= optionalNil               // "a"
b ??= optionalValue             // "optionalValue"
c ??= implicitlyUnwrappedNil    // "c"
d ??= implicitlyUnwrappedValue  // "implicitlyUnwrappedValue"

(请注意,您将在顶级范围内添加此定义,在任何类、结构或其他类型的定义之外)

于 2015-08-16T06:39:10.070 回答
6

从 2.0er 答案构建的 Swift 4.0 版本

/// Optional Assignment, assigns if value exists
infix operator ?=: AssignmentPrecedence

func ?=<T>(lhs: inout T, rhs: T?)  {

    guard let value = rhs else { return }
    lhs = value
}

// Playground Test

var dummy = "old"
var opt :String?

dummy ?= opt // leaves old

opt = "new"
dummy ?= opt // value becomes new 
于 2017-09-16T13:16:47.720 回答
2

在 swift 2 中是否有一种等效的方法可以在优雅的单行中表达这一点,而无需使用 if let i 添加中间变量?

如果您愿意,可以省略中间值:

if optionalInt != nil {
    nonOptionalInt = optionalInt!
}

如果您愿意,您显然可以将所有内容放在一行中:

if optionalInt != nil { nonOptionalInt = optionalInt! }

但如果您愿意,也可以使用三元运算符:

nonOptionalInt = (optionalInt != nil) ? optionalInt! : 0

其中0只是在 的情况下使用的默认值optionalInt == nil。如果您不想更改nonOptionalIntoptionalInt == nil则只需使用nonOptionalInt

nonOptionalInt = (optionalInt != nil) ? optionalInt! : nonOptionalInt

请注意,!inoptionalInt!隐式解包可选值——这是您告诉编译器您知道optionalInt不是nil这样的方式,因此可以分配给非可选变量。

于 2015-08-16T00:25:24.477 回答