为什么使用隐式解包或强制解包让应用程序在某个阶段崩溃没有好处?
Why using implicit unwrap or force unwrap letting the app crash at some stage not beneficial?
我的观点是在某些地方我们知道变量根本不会为 nil 但由于某些原因我们无法在 class 的 init 函数中实例化它所以我们必须它是可选的。
我也知道我们可以使用可选绑定或保护技术轻松摆脱它。
但在我看来,由于隐式 unwrap/force 解包,让应用程序因一些非常愚蠢的错误而崩溃对处于开发阶段的开发人员是有益的。
我的例子是:
class TopStoriesViewModelTests: XCTestCase {
var viewModel: TopStoriesViewModel!
override func setUp() {
super.setUp()
viewModel = TopStoriesViewModel(interactor: MockTopStoriesInteractor())
}
func testArticleDidVisited() {
viewModel.visited = xxxxxx
}
}
在这种情况下,我可以将 TopStoriesViewModel
设为 ?
然后保护它,或者如果在每个测试用例中都使用它,但我觉得没有必要。我知道我也可以使用 viewModel?.xxx
。但这不是重点。
我的问题是,在某些特定情况下(例如我给出的示例),强制 unwrapped/implicit 展开是有益的,我的观点是否正确。
当然可以。强制展开有许多正确的用途,崩溃只会在开发早期发生,因为已经犯了一个错误,一旦修复,崩溃就不会再发生。
一个常见的例子是从资源包中访问图像。一行如:
let imagePath = Bundle.main.path(forResource: "image", ofType: "png")!
如果开发人员忘记正确定位 image.png
,则应该会在早期开发中崩溃。一旦正确定位,该行就不会崩溃,因此没有理由处理可选路径。
其他常见的例子是奥特莱斯。它们通常被隐式解包,因为在视图控制器的代码中使用它们时,它们已经被附加。崩溃可能意味着插座未正确连接。它得到修复,没有更多的担心。无需处理警卫或其他可选检查。
最后一个例子(还有更多的可能性)。当从 table 视图中取出一个单元格时,将生成的单元格强制转换为自定义单元格类型。不需要守卫。我一直在这里看到代码,如果转换失败,代码会使用带有 as?
的守卫来抛出致命错误。只是强制施法。你用更少的代码得到同样的崩溃。一旦 table 视图和故事板正确,强制转换就不会失败。
话虽如此,较新的 Swift 开发人员应该暂时避免使用键盘上的 !
字符。知道何时安全地使用它是一项习得的技能。
如果潜在的崩溃完全在开发人员的控制之下,并且崩溃只是因为开发人员的失误而发生,那么使用 !
可能是合适的。
如果潜在的崩溃可能是由意外数据(JSON 解析、用户输入等)引起的,那么永远不要使用 !
。在这些情况下进行防御性编码。
tl;dr - 是的,在很多情况下强制解包、强制转换和隐式解包变量是正确的选择。
我的观点是在某些地方我们知道变量根本不会为 nil 但由于某些原因我们无法在 class 的 init 函数中实例化它所以我们必须它是可选的。
我也知道我们可以使用可选绑定或保护技术轻松摆脱它。
但在我看来,由于隐式 unwrap/force 解包,让应用程序因一些非常愚蠢的错误而崩溃对处于开发阶段的开发人员是有益的。
我的例子是:
class TopStoriesViewModelTests: XCTestCase {
var viewModel: TopStoriesViewModel!
override func setUp() {
super.setUp()
viewModel = TopStoriesViewModel(interactor: MockTopStoriesInteractor())
}
func testArticleDidVisited() {
viewModel.visited = xxxxxx
}
}
在这种情况下,我可以将 TopStoriesViewModel
设为 ?
然后保护它,或者如果在每个测试用例中都使用它,但我觉得没有必要。我知道我也可以使用 viewModel?.xxx
。但这不是重点。
我的问题是,在某些特定情况下(例如我给出的示例),强制 unwrapped/implicit 展开是有益的,我的观点是否正确。
当然可以。强制展开有许多正确的用途,崩溃只会在开发早期发生,因为已经犯了一个错误,一旦修复,崩溃就不会再发生。
一个常见的例子是从资源包中访问图像。一行如:
let imagePath = Bundle.main.path(forResource: "image", ofType: "png")!
如果开发人员忘记正确定位 image.png
,则应该会在早期开发中崩溃。一旦正确定位,该行就不会崩溃,因此没有理由处理可选路径。
其他常见的例子是奥特莱斯。它们通常被隐式解包,因为在视图控制器的代码中使用它们时,它们已经被附加。崩溃可能意味着插座未正确连接。它得到修复,没有更多的担心。无需处理警卫或其他可选检查。
最后一个例子(还有更多的可能性)。当从 table 视图中取出一个单元格时,将生成的单元格强制转换为自定义单元格类型。不需要守卫。我一直在这里看到代码,如果转换失败,代码会使用带有 as?
的守卫来抛出致命错误。只是强制施法。你用更少的代码得到同样的崩溃。一旦 table 视图和故事板正确,强制转换就不会失败。
话虽如此,较新的 Swift 开发人员应该暂时避免使用键盘上的 !
字符。知道何时安全地使用它是一项习得的技能。
如果潜在的崩溃完全在开发人员的控制之下,并且崩溃只是因为开发人员的失误而发生,那么使用 !
可能是合适的。
如果潜在的崩溃可能是由意外数据(JSON 解析、用户输入等)引起的,那么永远不要使用 !
。在这些情况下进行防御性编码。
tl;dr - 是的,在很多情况下强制解包、强制转换和隐式解包变量是正确的选择。