Swift 2:是否有一个简短的语法来从可选变量中有条件地设置一个非可选变量?

时间:2015-08-15 21:08:01

标签: swift2 optional-variables

有时候我发现自己写了这样的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 if i?

修改

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

显然有一种等效的方法

if optionalInt != nil {
    nonOptionalInt = optionalInt!
}

三元运营商? :不是等价的,因为它们可能会触发原始代码没有的didSet(如果这是预期的副作用,那就很好)

到目前为止,最优雅的答案似乎是

nonOptionalInt = optionalInt ?? nonOptionalInt

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

我认为我对Apple的愿望就像是

nonOptionalInt = optionalInt ?? 

nonOptionalInt ??= optionalInt

2 个答案:

答案 0 :(得分:10)

您要找的是nil coalescing operator

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

nonOptionalInt = optionalInt ?? nonOptionalInt

修改

re:您对问题的最后修改:

" 我认为我对Apple的愿望就像 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"

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

答案 1 :(得分:3)

从2.0er awnser

构建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