[英]Understanding the logic of an if let statement - variable used before being initialized
因此,我正在关注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!)
}
我不明白让tempItems常量的目的。
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]
是不能为nil的字符串数组
考虑下面的简化示例:
let foo: Any = 1
if let bar = foo as? Int { /* ... */ }
那么我们在最后一行做什么呢? 我们尝试将Any
实例( foo
)有条件地转换为Int
类型。 这样的条件类型转换( as?
)的结果是Optional
:
foo as? Int // type: Optional<Int>
接下来,我们尝试将可能成功的转换绑定到Int
类型的不变实例( bar
属性)。 有关详细信息,请参见语言指南中的可选绑定 。
现在,我们执行可选绑定的方法只是用于值绑定模式匹配的语法糖,在(给定成功的模式匹配)尝试将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 { /* .. */ }
理解以上内容的关键是要了解以下内容:
尝试的类型转换, as?
,将导致Optional<Wrapped>
实例,其中Wrapped
类型是类型转换的目标类型。 即, someInstance as? SomeType
someInstance as? SomeType
将导致Optional<SomeType>
的实例,该实例可能为nil
( .none
),或者可能包装了SomeType
的具体实例( .some(someInstanceOfSomeType)
)。
在Swift中,类型Optional<Wrapped>
的类型是,当排除所有特殊的整洁度/糖时,是一个枚举,
最后,值绑定模式匹配与赋值不同。
1)通过详尽的说明是不言自明的。 为了理解2)和3),我们可以研究以下简单示例,显示一个自定义的“可选”类enum
并带有一个持有通用关联值的用case
,对于一个给定的enum
实例,我们尝试有条件地绑定到物业:
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 { /* .. */ }
请注意上面最后一行中的值绑定,并与上面的上一代码片段中的非推荐的可选绑定进行比较。
最后,请注意,除了可选绑定之外,您还具有其他手段来访问(可选)(可能存在的)包装值并对其执行操作。 例如,使用Optional
的map(_:)
方法,为清楚起见,我们可以将您的示例代码(以及使items
不可变)简化为以下示例:
let items = (UserDefaults.standard.object(forKey: "items") as? [String])
.map { $0 + [textfield.text!] } ?? []
在单个表达式中使用以下内容:
UserDefaults
值的条件类型转换为类型[String]
textField.text!
到具体的[String]
值并分配给items
nil
合并运算符??
提供并清空数组[]
作为items
的默认值。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.