swift - 在测试属性是否存在时正确使用 guard 是什么

标签 swift

在我的代码中,系统向我传递了一本字典。该字典可以包含错误字符串。像这样

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/

相关文章:

ios - 为什么我们不能直接在 oc 或 swift 中捕获 Kotlin 代码产生的异常?

ios - 我如何扩展/子类化 Array 以便它索引它的项目?

ios - 如何使用 prepare for segue 传递 Firebase UID

json - 从 post 方法中检索 json 数据并附加到数组

ios - xcode MKMapView 确实失败,错误为 : Error Domain=kCLErrorDomain Code=1 "(null)"

arrays - 字典,其中值包含字典,值包含数组

ios - 在导航栏上方制作容器 View

ios - 无法理解崩溃日志部分应用转发器来关闭 #1

ios - SpriteKit Swift 中的 NSInvalidArgumentException

ios - Swift - 根据 UITextView 布局约束的 UITableViewCell 高度