错误处理优化

Error handling optimization

我只是在玩 2.0 版中的新错误处理。我现在有以下功能:

func decodeHTML(HTML: String) throws {
    guard let remove : String? = HTML.componentsSeparatedByString("<div id=\"loading\" style=\"display: none;\">")[0] else { throw DecodeError.MatchError }
    guard var splitter : [String]? = remove!.componentsSeparatedByString("<div class=\"info\">") else { throw DecodeError.MatchError }
    if splitter!.count > 0 { splitter!.removeFirst() }
    if splitter!.count > 0 { splitter!.removeLast() }

    if splitter!.count > 0 {
        for HTMLmessage in splitter! {
            guard var splitter2 : [String]? = HTMLmessage.componentsSeparatedByString("</td><td>Besked fra ") else { throw DecodeError.MatchError }
            guard let author : String? = (splitter2![1].componentsSeparatedByString("</tr>"))[0] else { throw DecodeError.MatchError }
            guard let date : String? = (splitter2![0].componentsSeparatedByString("<td width=\"25%\">"))[1] else { throw DecodeError.MatchError }
            guard let title : String? = HTMLmessage.componentsSeparatedByString("\"><b>")[1].componentsSeparatedByString("</b></a></td></tr>")[0] else { throw DecodeError.MatchError }
            guard var string : String? = HTMLmessage.componentsSeparatedByString("</a></td></tr><tr><td colspan=2>")[1].componentsSeparatedByString("</td></tr></table></div>")[0] else { throw DecodeError.MatchError }
            string = string!.stringByReplacingOccurrencesOfString("</p><p>", withString: "\n")
            string = string!.stringByReplacingOccurrencesOfString("<[^>]+>", withString: "", options: .RegularExpressionSearch, range: nil)

            self.messages.append(message(author, date, title, string))
        }
    } else {
        throw DecodeError.MatchError
    }
}

但我想知道,我真的必须每次都警惕出问题吗?如果其中一行失败,是否有更简单的方法来抛出错误?

我建议你创建一个包装函数:

func componentsSeparatedByString(string: String) throws -> String {
    let texts = HTMLmessage.componentsSeparatedByString(string)

    if texts.count > 0
        return texts[0]
    } else {
        throw DecodeError.MatchError
    }
}

现在您可以多次调用此函数并使用单个 catch 块:

do {
    let text1 = try componentsSeparatedByString("text1")
    let text2 = try componentsSeparatedByString("text2")
    let text3 = try componentsSeparatedByString("text3")
} catch {
    print("Something went wrong!")
}

我稍微清理了你的函数:

extension String {
    func split(string: String) -> [String] { return componentsSeparatedByString(string) }
}

extension Array {
    var second : Element? { return dropFirst().first }
}

func decodeHTML(HTML: String) throws {
    guard let
        splitter = HTML
            .split("<div id=\"loading\" style=\"display: none;\">").first?
            .split("<div class=\"info\">").dropFirst().dropLast()
    where !splitter.isEmpty else {
        throw DecodeError.MatchError
    }

    for HTMLmessage in splitter {
        let splitter2 = HTMLmessage.split("</td><td>Besked fra ")

        guard let
            author = splitter2.second?
                .split("</tr>").first,
            date = splitter2.first?
                .split("<td width=\"25%\">").second,
            title = HTMLmessage
                .split("\"><b>").second?
                .split("</b></a></td></tr>").first,
            string = HTMLmessage
                .split("</a></td></tr><tr><td colspan=2>").second?
                .split("</td></tr></table></div>").first?
                .stringByReplacingOccurrencesOfString("</p><p>", withString: "\n")
                .stringByReplacingOccurrencesOfString("<[^>]+>", withString: "", options: .RegularExpressionSearch, range: nil)
        else {
            throw DecodeError.MatchError
        }

        let message = (author, date, title, string)

    }
}

您可以使用 dropFirstdropLastfirst 来安全地访问元素。不过,您可能真的应该使用 HTML 解析库。