在我的代码中,系统向我传递了一本字典。该字典可以包含错误字符串。像这样
func handleSomething(_ json: [String: Any]) -> (Bool, String?) {
if let error = json["error"] as? String {
print("I have an error: \(error)")
return (false, error)
}
...
return (true, nil)
}
我认为这将是使用守卫的好地方,但是代码并不那么简洁
func handleSomething(_ json: [String: Any]) -> Bool {
let error = json["error"] as? String
guard error == nil else {
print("I have an error: \(error!)")
return (false, error)
}
...
return (true, nil)
}
有没有更好的方法可以在一行中完成赋值和检查?如果不是,这就是 guard 的正确用法吗?
更新: 添加了返回值以更好地说明问题的真正意图。
最佳答案
通常,您应该强烈避免传递 [String: Any]
。您应该更早地将其解析为更强的数据类型,并且您应该在那里分离出错误情况,通常使用枚举:
struct ServerData {
// good data; no errors
}
enum ServerResponse {
case success(ServerData)
case error(String) // Return this if error is set
}
有了这个,我们的函数将主要采用 ServerData
,因此错误已经得到处理。只要有可能,不要想出聪明的解决方法来解决问题,而是让整个问题消失。
也就是说,仍然有解析器本身需要处理,这种情况可能会出现,甚至当你有更强的类型时。在许多情况下,您经常会遇到这种保护/日志模式,绝对值得避免这种情况。于是拉出一个函数:
func noErrorOrLog(_ json: [String: Any]) -> Bool {
if let error = json["error"] as? String {
print("I have an error: \(error)")
return false
}
return true
}
现在实际的处理函数可以使用 guard
并避免重复记录:
func handleSomething(_ json: [String: Any]) -> Bool {
guard noErrorOrLog(json) else {
return false
}
// ...
}
在某些情况下,这没有意义(如果您只执行一次),在这种情况下,if-let
是正确的工具。创建混淆代码来创建 guard
会适得其反。但在许多情况下,您可以完全避免此问题(通过较早地使用强类型过滤错误),或通过移至函数来避免重复。
关于swift - 在测试属性是否存在时正确使用 guard 是什么,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46426503/