理解if let语句的逻辑 - 在初始化之前使用的变量

时间:2017-04-17 14:29:45

标签: ios swift if-statement nsuserdefaults

所以我按照udemy的教程编写了这段代码。

   let itemsObject = UserDefaults.standard.object(forKey: "items")
    var items:[String]

    if let tempItems = itemsObject as? [String]
    {
        //
        items = tempItems
        items.append(textfield.text!)
    }

我理解itemsObject和items数组,但我想知道为什么我不能完全绕过tempItems常量...

var items:[String]
if items = itemsObject as? [String]
{
items.append(textfield.text!)
}

我不理解let tempItems常量的用途。

2 个答案:

答案 0 :(得分:0)

let itemsObject = UserDefaults.standard.object(forKey: "items")

itemsObject现在属于Any?类型所以我们需要做两件事:抛出它并检查它是否为零

if let tempItems = itemsObject as? [String]

是:

的快捷方式
let tempItems1 = itemsObject as? [String] // cast to [String]?
if tempItems1 != nil {
    let tempItems2 = tempItems1! // we know its not nil, so force unwrap it to [String]
    ...
}

提示:

[String]?是一个字符串数组,可以是nil

[String]是一个不能为零的字符串数组

答案 1 :(得分:0)

可选绑定是值绑定模式匹配,不等同于赋值

考虑以下简化示例:

let foo: Any = 1

if let bar = foo as? Int { /* ... */ }

那么我们在最后一行做什么呢?我们尝试有条件地将Any实例(foo)转换为Int类型。这种条件类型转换(as?)的结果是Optional

foo as? Int // type: Optional<Int>

继续,我们尝试可选地将可能成功的转换绑定到类型为Int的不可变具体实例(bar属性)。有关详细信息,请参阅语言指南中的optional binding

现在,我们执行可选绑定的方式只是value-binding pattern matching的语法糖,在(给定成功的模式匹配)上下文中尝试将enum个案的关联值绑定到属性。可选绑定的语法糖可用于极端常见的Optional<Wrapped>枚举类型,而对于其他enum类型,我们需要使用通用值绑定模式语法

if case let .anEnumCase(bindAssociatedValueToMe) = someEnumInstance { /* ... */ }

// alternatively
if case .anEnumCase(let bindAssociatedValueToMe) = someEnumInstance { /* ... */ }

即,以下两个(三个)是等价的

// make use of syntactic sugar available for `Optional` enum
if let bar = foo as? Int { /* .. */ }

// or use the explicit value-binding pattern available to any
// enum with a case that holds and associated value
if case .some(let bar) = foo as? Int { /* .. */ }

// (for the latter: alternatively)
if case let .some(bar) = foo as? Int { /* .. */ }

并且,为了给这个问题添加一些额外的混淆,我们还有另一个特殊的语法糖可用于特殊的枚举Optional<Wrapped>(特别是.some(let bindWrappedToThis)的情况),这样以下也是等价的到上面两个:

// using the sugar '_?' instead of '.some(_)', here replacing
// '... let .some(bar)' with '... let bar?'
if case let bar? = foo as? Int { /* .. */ }

理解上述内容的关键是理解以下内容:

  1. 使用as?进行的尝试类型转换将导致Optional<Wrapped>实例,其中Wrapped类型是类型转换的目标类型。即,someInstance as? SomeType将生成Optional<SomeType>的实例,可能是nil.none),或者可能包含SomeType的具体实例({ {1}})。

  2. Swift中的.some(someInstanceOfSomeType)类型,当省略所有特殊的整洁/糖时,枚举,

  3. 最后,该值绑定模式匹配与赋值不同。

  4. 1)通过详尽的描述是不言自明的。要理解2)&amp; 3),我们可以研究以下简单示例,显示一个自定义&#34;可选&#34;类似Optional<Wrapped>,其中enum包含一个通用关联值,对于给定的实例, case,我们尝试有条件地绑定到属性:

    enum

    注意上面最后一行中的值绑定,并与上面上面代码片段中的非加糖可选绑定进行比较。

    最后,请注意,除了可选绑定之外,您还可以访问并对可选的(可能存在的)包装值执行操作。例如。使用map(_:) method of Optional时,为了清晰起见,我们可以在您的热门代码段中将您的示例(以及enum MyOptional<Wrapped> { case none case some(Wrapped) } // instantiate with a case with an associated value let foo = MyOptional.some(1) // MyOptional<Int>.some(1) // use value-binding pattern matching to conditionally // access the associated value of the 'some(...)' case, // given that 'foo' is '.some' (and not '.none') if case .some(let bar) = foo { /* .. */ } 不可变)压缩为以下内容:

    items

    在单个表达式中,使用以下内容:

    • let items = (UserDefaults.standard.object(forKey: "items") as? [String]) .map { $0 + [textfield.text!] } ?? [] 值的条件类型转换为UserDefaults
    • 类型
    • 如果类型转换成功,请将[String]附加到具体的textField.text!值并分配给[String]
    • 如果类型转换失败,请使用items合并运算符nil提供并清空数组??,作为[]的默认值。