首页 > 解决方案 > 尝试以正确的方式处理错误和可选项

问题描述

我正在尝试使用 SwiftSoup 来抓取一些 HTML。这个示例基于 SwiftSoup github 文档,运行良好……</p>

func scrape() throws {

  do {
    let htmlFromSomeSource = "<html><body><p class="nerp">HerpDerp</p><p class="narf">HoopDoop</p>"

    let doc = try! SwiftSoup.parse(htmlFromSomeSource)
    let tag = try! doc.select("p").first()!
    let tagClass = try! tag.attr("class")
  } catch {
    print("oh dang")
    throw Abort(.notFound)
  }
  print(tagClass)
}

…直到我弄乱了选择器或属性目标,此时由于隐式解包的选项(我认为这只是让更聪明的人开始的快速而肮脏的代码),一切都崩溃了。那 do/catch 似乎根本没有帮助。

那么正确的方法是什么?这编译...

print("is there a doc?")
guard let doc = try? SwiftSoup.parse(response.body.description) else {
  print("no doc")
  throw Abort(.notFound)
}

print("should halt because there's no img")
guard let tag = try? doc.select("img").first()! else {
  print("no paragraph tag")
  throw Abort(.notFound)
}

print("should halt because there's no src")
guard let tagClass = try? tag.attr("src") else {
  print("no src")
  throw Abort(.notFound)
}

...但是如果我弄乱了选择器或属性,它会再次崩溃,“在展开可选值时意外发现 nil”(在“是否有文档?”之后)。我认为当遇到 nil 时,guard 会停止该过程?(如果我将“try?”转换为“try”,编译器会抱怨“条件绑定的初始化程序必须具有可选类型”......)

标签: swifterror-handlingoptionalswiftsoup

解决方案


如果您声明该函数,因为throws您不需要do - catch函数内的块。只需删除块和感叹号后将try错误传递给调用者函数。

func scrape() throws { // add a return type
    let htmlFromSomeSource = "<html><body><p class="nerp">HerpDerp</p><p class="narf">HoopDoop</p>"

    let doc = try SwiftSoup.parse(htmlFromSomeSource)
    guard let tag = try doc.select("p").first() else { throw Abort(.notFound) }
    let tagClass = try tag.attr("class")
    // return something 
}

推荐阅读