Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Error handling optimization

Tags:

swift

throw

I am just playing with the new error handling in version 2.0. And I now have the following functions with a throw:

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

But I wonder, do I really have to guard everytime something can go wrong? Is there an easier way to throw an error if one of the lines fails?

like image 625
magnuskahr Avatar asked May 30 '26 03:05

magnuskahr


1 Answers

I cleaned up your function a bit:

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)

    }
}

You can use dropFirst, dropLast and first to get access to elements safely. You should probably really use a HTML parsing library though.

like image 92
Kametrixom Avatar answered May 31 '26 17:05

Kametrixom



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!