Return 文件如果存在,否则 return false

Return file if exists, otherwise return false

我正在尝试创建一个字符串扩展,用于在我的应用程序目录中搜索文件,如果该文件不存在,则 return 为 false。这是我拥有的:

extension String {
    func doesFileWithNameExist() -> Bool {
        let path = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0] as String
        let url = NSURL(fileURLWithPath: path)
        let filePath = url.appendingPathComponent(self+".png")?.path
        let fileManager = FileManager.default
        if fileManager.fileExists(atPath: filePath!) {
            return true
        } else {
            return false
        }
    }
}

现在我的函数只是 return 一个 Bool,但我想知道是否有办法只 return 文件(如果它存在),否则 return false。有没有办法从函数中 return 不同的值类型?

你可以return一个可选的值,在Swift中是"a thing or nil"——非常接近"that file or false."例如,这里有一个对你的扩展函数的快速调整,如果文件存在,则 returns 路径,否则为 nil:

extension String {
    func doesFileWithNameExist() -> String? {
        let path = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0] as String
        let url = NSURL(fileURLWithPath: path)
        let filePath = url.appendingPathComponent(self+".png")?.path
        let fileManager = FileManager.default
        if fileManager.fileExists(atPath: filePath!) {
            return filePath
        } else {
            return nil
        }
    }
}

不过,快速编辑评论:这种行为似乎并不特别 well-suited 字符串扩展。我会考虑在 FileManager 上写一个扩展,传入一个字符串作为文件名。考虑到 "png" 扩展的硬编码,也许有以下签名?

extension FileManager {
    func pathToExistingPNGFile(named name: String) -> String? {
        // …
    }
}

强烈推荐使用 URL 相关的 API。这 returns 一个可选的 UIImage:

extension String {
    func doesFileWithNameExist() -> UIImage? { // maybe better pngImageInDocumentsFolder()
        let fileManager = FileManager.default
        do {
            let url = try fileManager.url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: false)
            let fullURL = url.appendingPathComponent(self).appendingPathExtension("png")
            _ = try fullURL.checkResourceIsReachable()
            let data = try Data(contentsOf: fullURL)
            return UIImage(data: data)
        } catch {
            return nil
        }
    }
}

或者用Leo的大减法(还是稍微减法):

var image: UIImage? { 
    guard let url = try? FileManager.default.url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: false).appendingPathComponent(self).appendingPathExtension("‌​png"), 
          let data = try? Data(contentsOf: url) else { return nil }
    return UIImage(data: data) 
}