Swift 4替代如果让

时间:2017-12-07 20:32:46

标签: swift optional

我有这个代码,它会检查文件目录中是否存在文件,是否使用此文件来设置控制器的数据,如果它没有使用捆绑包中的文件供应商,如果也失败了它设置了一个空的视图控制器。

有没有办法有条件地设置url变量,以便我可以编写parse(fromFile:)方法一次而不是if if?最直观的方式似乎是if let url = something || let url = somethingElse然后在括号中的parse(fromFile: url)中执行,但似乎用swift不可能。

if let url = try? FileManager().url(for: .documentDirectory,
                                    in: .userDomainMask,
                                    appropriateFor: nil,
                                    create: true).appendingPathComponent("database.json") {
    parse(fromFile: url)
} else if let url = Bundle.main.url(forResource: "database", withExtension: "json") {
    parse(fromFile: url)
} else {
    setUpWithNothing()
}

3 个答案:

答案 0 :(得分:4)

我建议将代码分成几个步骤:

let documentsUrl = try! FileManager.default.url(
    for: .documentDirectory,
    in: .userDomainMask,
    appropriateFor: nil,
    create: true
)

文档目录应始终存在,因此我不太担心使用try!。但是,如果您担心,您应该单独解决该特殊情况,例如:使用:

 guard let documentUrl = try? ... else {
     setUpWithNothing()
     return
 }

然后:

let fileUrl = documentUrl.appendingPathComponent("database.json")

此调用永远不会失败,它不会检查文件是否存在。您需要明确检查存在:

let fileExists = FileManager.default.fileExists(atPath: fileUrl.path)

let defaultUrl = Bundle.main.url(forResource: "database", withExtension: "json")
let databaseUrl = fileExists ? fileUrl : defaultUrl!

同样,你不应该担心你的包中存在文件,如果你知道它在那里并且只是打电话:

parse(fromFile: databaseUrl)

但是,如果您需要格外小心,只需删除!并使用:

if let databaseUrl = fileExists ? fileUrl : defaultUrl {
    parse(fromFile: databaseUrl)
} else {
    setUpWithNothing()
}

答案 1 :(得分:3)

您可以使用nil-coalescing operator (??)

如果使用FileManager的表达式返回nil(通过抛出,感谢try?),则将使用Bundle.main.url(...)代替。

如果这也是nil,则条件绑定将完全失败,else块将运行setUpWithNothing()

if let url = (try? FileManager.default.url(for: .documentDirectory,
                                           in: .userDomainMask,
                                           appropriateFor: nil,
                                           create: true
                                           ).appendingPathComponent("database.json"))
             ?? Bundle.main.url(forResource: "database", withExtension: "json") {
    parse(fromFile: url)
} else {
    setUpWithNothing()
}

答案 2 :(得分:2)

由于你在前两种情况下做了同样的事情而在第二种情况下做了不同的事情,所以这是它自己功能的一个很好的选择:

func databaseFileURL() -> URL? {
    if let url = try? FileManager().url(for: .documentDirectory, in: .userDomainMask,
                                        appropriateFor: nil, create: true) {
        return url.appendingPathComponent("database.json")
    } 
    else { 
        return Bundle.main.url(forResource: "database", withExtension: "json")
    }
}

然后你就可以了

if let url = databaseFileURL() {
    parse(fromFile: url)
} else {
    setUpWithNothing()
}

它很好地区分了问题,使其在使用时更清洁,更清晰。如果你需要对文件做任何其他事情,你可以调用函数而不是复制粘贴逻辑。