Swift可选操作员使用

时间:2015-05-28 16:03:31

标签: swift

//declaration

private var delegate: MyDelegate?

我应该使用这个

delegate!.result(data)

或者

delegate?.result(data)

在第一个版本中,我认为如果没有定义委托,程序将崩溃,但是在第二个版本中,如果没有定义委托,程序可能不会调用代理。

我的问题和关注是关于崩溃并立即让我知道我做错了(我想知道)或者是一个无声的错误(我忘了通过委托)这需要一些时间来弄明白,这是更好的方法?

3 个答案:

答案 0 :(得分:3)

1)失败并非必须保持沉默:

if let myData = delegate?.result(data) {
    // do something with myData
} else {
    // handle the fact that the delegate didn't work
}

2)我认为由于强制解包!而导致崩溃是一个坏主意:如果你在测试期间错过了它,它会在运行时将问题推迟给用户。相反,开发人员应该在编译时处理问题;通过Optionals,Swift可以帮助实现这一目标。

答案 1 :(得分:2)

这实际上取决于您的设计需求。通常delegate是可选的,因此您的?选项主要用于此模式。

也就是说,如果你真的想强制执行委托,你可以限制它在你指定的初始化程序中定义。

另一个选项是在从Interface Builder声明属性时在Xcode中看到的设计:隐式解包用于让init进程终止,然后解码器应该解码并分配所有出口。 因此,您会看到!。在这种情况下,出口应始终存在,否则欢迎碰撞。

最后,我通常会使用一个可选的代表作为委托。但如果我想强制执行它,我会在初始化过程中强制执行它。这样你就不会忘记从一开始就传递一个具体的代表; - )

答案 2 :(得分:2)

就个人而言,我认为!.是一个好主意的时代相当罕见。当然,你可能宁愿在生产中默默地失败,除非它是完全关键的。如果进度条绘图中的错误导致应用程序崩溃,那将是一种耻辱。如果操作对于您的应用程序正常运行至关重要并且至关重要,请对其进行适当的错误处理!也许告诉你的用户有什么不对劲。

作为妥协,你可以考虑这样的事情:

func assertOnNil<T>(msg: String, defaultVal: T)->T {
    assertionFailure(msg)
    return defaultVal
}

func assertOnNil(msg: String)->() {
    assertionFailure(msg)
    return
}

// this will assert in debug builds
let x = "foo".toInt()?.successor() ?? assertOnNil("Should have been a number",0)
// this will print 0 in release builds
println(x)  


struct S {
    func f()->() { println("S.f") }
}

let s: S? = nil

// this will assert in debug builds but fail silently on release
s?.f() ?? assertOnNil("do-nothing chain")

这可以适用于记录错误消息或改为抛出错误对话。