Swift 2如果让do-try-catch

时间:2015-06-09 16:53:01

标签: swift

在Swift 1.2中我有这个:

if let filePath = NSBundle.mainBundle().pathForResource("some", ofType: "txt"),
       data = String(contentsOfFile: filePath, encoding: NSUTF8StringEncoding) {
    for line in data.componentsSeparatedByCharactersInSet(NSCharacterSet.newlineCharacterSet()) {
        // Do something
    }      
} else {
    println("some.txt is missing")
}

在Swift 2中,我不能再这样做,因为pathForResourcecontentsOfFile都可以抛出,也可以返回选项。我可以解决它,但它现在看起来非常冗长:

do {
    if let filePath = try NSBundle.... {
        do {
            if let data = try String.... {
                for line in data..... {
                    // Do something
                }
            } else {
                print("Nil data")
            }
        } catch {
            print("contentsOfFile threw")
        }
    } else {
        print("Nil pathForResource")
    }
} catch {
    print("pathForResource threw")
}      

我希望我错过了一些东西 - 任何帮助都会受到赞赏。

2 个答案:

答案 0 :(得分:13)

使用保护语法而不是if-let。

以下是一个示例:

do {

    guard let filePath = try NSBundle .... else {
        // if there is exception or there is no value
        throw SomeError
    }
    guard let data = try String .... else {
    }

} catch {

}

if-let和guard之间的区别在于未展开值的范围。如果使用if-let filePath值仅在if-let块内可用。如果使用guard filePath值可用于调用的守护进程。

这是swift book中的相关部分

  

一个保护语句,就像if语句一样,执行语句依赖   在表达式的布尔值上。你使用一个守卫声明   要求条件必须为true才能使代码在。之后   守卫声明将被执行。与if语句不同,是一名警卫   语句总是有一个else子句 - else`子句中的代码   如果条件不成立则执行。

答案 1 :(得分:8)

我可以说,只有上面的String初始值设定项实际上会抛出一个错误(尽管pathForResource()可能会从返回一个可选值变为在某个时候抛出错误)。因此,以下内容应该复制您之前所做的事情:

if let filePath = NSBundle.mainBundle().pathForResource("some", ofType: "txt") {
    do {
        let data = try String(contentsOfFile: filePath, encoding: NSUTF8StringEncoding)
        for line in data.componentsSeparatedByCharactersInSet(NSCharacterSet.newlineCharacterSet()) {
                // Do something
        }
    } catch {
        print("Couldn't load the file somehow")
    }
} else {
    print("some.txt is missing")
}

您的字符串不再是可选字符,因此不需要if let

正如mustafa指出的那样,guard语句可用于删除成功案例中的缩进级别:

guard let filePath = NSBundle.mainBundle().pathForResource("some", ofType: "txt") else {
    print("some.txt is missing")
}
do {
    let data = try String(contentsOfFile: filePath, encoding: NSUTF8StringEncoding)
    for line in data.componentsSeparatedByCharactersInSet(NSCharacterSet.newlineCharacterSet()) {
        // Do something
    }
} catch {
    print("Couldn't load the file somehow")
}

现在,如果pathForResource()从返回可选项更改为抛出错误,则可以按顺序使用这些try语句:

do {
    let filePath = try NSBundle.mainBundle().pathForResource("some", ofType: "txt")
    let data = try String(contentsOfFile: filePath, encoding: NSUTF8StringEncoding)
    for line in data.componentsSeparatedByCharactersInSet(NSCharacterSet.newlineCharacterSet()) {
        // Do something
    }
} catch {
    print("some.txt is missing")
}

抛出错误的第一个语句将在那时发生,阻止执行任何过去的操作。单个catch语句足以从一系列可用的操作中获取任何内容,这使得链接它们变得容易。