试图以正确的方式处理错误和可选项

时间:2018-04-27 16:04:37

标签: swift error-handling optional swiftsoup

我试图使用SwiftSoup来抓取一些HTML。这个例子基于SwiftSoup github文档,工作得很好......

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)
}

......直到我弄乱了选择器或属性目标,此时所有内容都崩溃了,这要归功于隐式解包的选项(我认为只是快速而肮脏的代码才能让更聪明的人开始)。这样做/捕获似乎没有任何帮助。

那么正确的道路是什么?这编译......

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)
}

...但是如果我弄乱了选择器或属性它会崩溃,&#34;在解开一个Optional值时,意外地发现了nil&#34; (&#34;是否有文件?&#34;)。我认为当遇到nil时,后卫会停止这个过程吗? (如果我转换&#34;尝试?&#34;到&#34;尝试&#34;编译器抱怨&#34;条件绑定的初始化程序必须具有可选类型&#34; ...)

1 个答案:

答案 0 :(得分:2)

如果您将该函数声明为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 
}