Swift 如何在赋值后使用guard语句检测nil?

Swift 如何在赋值后使用guard语句检测nil?,swift,Swift,我正试着用守卫声明来检查nil 我不明白为什么下面的代码会漏掉,并生成一个坏的\u EXEC错误: guard let event:Event! = eventsImagesLoading.removeValueForKey(location) else { return } images[location] = responseData event!.iconImgData = images[location] 我试图在方法调用之后检查“eve

我正试着用守卫声明来检查nil

我不明白为什么下面的代码会漏掉,并生成一个坏的\u EXEC错误:

    guard let event:Event! = eventsImagesLoading.removeValueForKey(location) else {
        return
    }
    images[location] = responseData
    event!.iconImgData = images[location]

我试图在方法调用之后检查“event”是否为nil。如果是的话,它应该马上回来。但事实上,它在活动中滑过并崩溃了!。iconImageData。。。行。

更改
事件
事件
(第1行)和
事件
事件
(第5行)。

更改
事件
事件
(第1行)和
事件
事件(第5行)。

其他答案向您展示了如何解决您的问题,但没有真正解释为什么会发生此错误,因此我想我会参与其中


守卫让。。。else
语句,很像
if let…
,尝试将可选项的未包装值绑定到同一基础类型的非可选不可变项,通常只要该值不是
nil
;使用可选绑定

var a: Int? = 5
if let b = a {
    // b unwrapped, type inferred to non-optional type Int
    print(b) // "5"
}
如果
a
的值为
nil
,则上述绑定将失败,因为
b
,根据默认值(通过类型推断),其类型为
Int
,不能保持
nil

在这种情况下,显式地将
b
声明为隐式展开的可选项是没有意义的,因为这将允许成功绑定,即使
a
为零。等效的非感测块将明确声明
b
为可选,在可选
a
Int?
)到可选
b
Int?
)的“尝试可选绑定”自然会成功之后,而
if let…
块减少为完全冗余的块本地分配

a = nil

if let b: Int! = a {
    print(b) // "nil"
    // wups, we managed to bind a to b even though a is nil ...

    // note also this peculiarity
    print(b.dynamicType) // Optional<Int>
    let c: Int! = nil
    print(c.dynamicType) // ImplicitlyUnwrappedOptional<Int>
}

if let b: Int? = a {
    print(b) // nil
    // wups, we managed to bind a to b even though a is nil ...
}
对于需要延迟初始化(值
nil
直到初始化)的不可变项,通常只应使用隐式展开选项。初始化隐式展开的可选项后,其值永远不应为
nil
(而在上面的示例中,通过可选绑定初始化后,其值仅为;
nil

另外,您通常应该让编译器在
guard let expert_THIS=。。。else
如果让我们推断这=…
子句



我们可以考虑是否应该允许它对可选类型使用可选绑定(保证成功),但这是另一个讨论。

其他答案向您展示了如何解决您的问题,但没有真正解释为什么会发生此错误,所以我想我会参与讨论


守卫让。。。else
语句,很像
if let…
,尝试将可选项的未包装值绑定到同一基础类型的非可选不可变项,通常只要该值不是
nil
;使用可选绑定

var a: Int? = 5
if let b = a {
    // b unwrapped, type inferred to non-optional type Int
    print(b) // "5"
}
如果
a
的值为
nil
,则上述绑定将失败,因为
b
,根据默认值(通过类型推断),其类型为
Int
,不能保持
nil

在这种情况下,显式地将
b
声明为隐式展开的可选项是没有意义的,因为这将允许成功绑定,即使
a
为零。等效的非感测块将明确声明
b
为可选,在可选
a
Int?
)到可选
b
Int?
)的“尝试可选绑定”自然会成功之后,而
if let…
块减少为完全冗余的块本地分配

a = nil

if let b: Int! = a {
    print(b) // "nil"
    // wups, we managed to bind a to b even though a is nil ...

    // note also this peculiarity
    print(b.dynamicType) // Optional<Int>
    let c: Int! = nil
    print(c.dynamicType) // ImplicitlyUnwrappedOptional<Int>
}

if let b: Int? = a {
    print(b) // nil
    // wups, we managed to bind a to b even though a is nil ...
}
对于需要延迟初始化(值
nil
直到初始化)的不可变项,通常只应使用隐式展开选项。初始化隐式展开的可选项后,其值永远不应为
nil
(而在上面的示例中,通过可选绑定初始化后,其值仅为;
nil

另外,您通常应该让编译器在
guard let expert_THIS=。。。else
如果让我们推断这=…
子句


我们可以考虑是否应该允许它对可选类型使用可选绑定(保证成功),但这是另一个讨论。

它没有滑过——当到达
let event:event
,当您试图将
nil
事件(由
guard
处理)强制为非可选类型时。@James:实际上,它正在顺利通过,因为将可选类型分配(“绑定”)到同一可选类型总是会成功的。隐式解包选项可能会保留值
nil
(无运行时异常),但在值
nil
时不应使用,因为这相当于它们未初始化(因为作为开发人员,我们应该只在知道它们不保留值
nil
时使用它们)。因此,
guard让。。。否则上面的
块将始终滑过,因为赋值(“绑定”)将始终成功。它不会滑过——当到达
let event:event时,会发生错误的执行
,当您试图将
nil
事件(由
guard
处理)强制为非可选类型时。@James:实际上,它正在顺利通过,因为将可选类型分配(“绑定”)到同一可选类型总是会成功的。隐式解包选项可能会保留值
nil
(无运行时异常),但在值
nil
时不应使用,因为这相当于它们未初始化(因为作为开发人员,我们应该只在知道它们不保留值
nil
时使用它们)。因此,代码