如何使用guard语句在分配后检测nil?

时间:2016-03-30 07:58:47

标签: swift

我试图使用guard语句来检查nil。

我很困惑为什么以下内容让它漏掉并产生BAD_EXEC错误:

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

我试图检查"事件"方法调用后为零。如果它是它应该返回。但实际上它会在事件中滑倒并崩溃!.iconImageData ... line。

3 个答案:

答案 0 :(得分:5)

其他答案向您展示如何解决您的问题,但并未真正解释为什么会出现此错误,所以我认为我会参与其中。

guard let ... else语句与if let ...非常相似,尝试将可选的unwrapped值绑定到一个非nil ---可选的不可变的相同底层类型;使用可选绑定

var a: Int? = 5
if let b = a {
    // b unwrapped, type inferred to non-optional type Int
    print(b) // "5"
}

如果a的值为nil,则bInt,默认情况下(按类型推断),类型为nil的类型b无法保留,则上述绑定将失败a

在这种情况下,将b显式声明为隐式展开的可选项是没有意义的,因为即使a为nil,这也将允许成功绑定。等效的非感知块将明确声明Int?是可选的,然后将可选bInt?)的“尝试可选绑定”转换为可选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 ... } }自然会一直成功,b块会减少为完全冗余的块本地分配。

Int?

注意特殊性,无论我们是否明确指定Int!b类型(可选)或类型if let(隐式展开可选),绑定不可变{{1}在两种情况下,传入Int?块只是一个常规可选(类型为event)。这解释了为什么您需要在<{em} event!.iconImgData子句之后展开guard letguard let ... else,即使我们声明它是隐式展开的类型。

因此,在您的示例中,eventsImagesLoading.removeValueForKey(location)语句不会捕获nilevent的情况,作为对Event!的绑定(隐式解包的可选类型) nil)即使对func foo() { let bar : Int? = nil guard let _: Int! = bar else { print("this is surely nil") return } print("but an implicitly unwrapped optional will fall through") } foo() // "but an implicitly unwrapped optional will fall through" 个案件也会成功。

nil

对于需要延迟初始化(值nil直到初始化)的不可变项,通常只应使用隐式解包的选项。在初始化隐式展开的可选项之后,其值永远不应该是nil(而在上面的示例中,它的值是,在通过可选绑定初始化之后,只是那个; guard let INFER_THIS = ... else)。

此外,您通常应该让编译器推断您尝试在if let INFER_THIS = ..../configure make ASTLDFLAGS="-lcurl" make install make samples make config 子句中绑定的不可变的非可选类型。 / p>

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

答案 1 :(得分:3)

Event!更改为Event(第1行),将event!更改为event(第5行)。

答案 2 :(得分:1)

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