4

我习惯于在 Objective-C 中编写具有早期返回/黄金路径的代码。!我在 Swift 中尝试了这种方法,并注意到当涉及可选时,提前返回是以使用强制展开运算符 ( ) 为代价的。

采取一种计算目录大小的方法。一、黄金之路版本:

private func calculateSize_GoldenPath(directory:String) -> UInt64 {
    let fileManager = NSFileManager.defaultManager()
    var error : NSError?
    var contents = fileManager.contentsOfDirectoryAtPath(directory, error: &error) as [String]?
    if contents == nil {
        NSLog("Failed to list directory with error \(error)")
        return 0
    }
    var size : UInt64 = 0
    for pathComponent in contents! {
        let path = directory.stringByAppendingPathComponent(pathComponent)
        let attributes : NSDictionary? = fileManager.attributesOfItemAtPath(path, error: &error)
        if (attributes == nil) {
            NSLog("Failed to read file size of \(path) with error \(error)")
            continue
        }
        size += attributes!.fileSize()
    }
    return size;
}

请注意我如何将!运算符用于contentsattributes变量。

我假设过度使用!运算符会破坏选项的目的以及它们带来的类型安全性。这就是我觉得上述方法应该在 Swift 中编码以避免强制展开的方式:

private func calculateSize_IfLet(directory:String) -> UInt64 {
    let fileManager = NSFileManager.defaultManager()
    var error : NSError?
    if let contents = fileManager.contentsOfDirectoryAtPath(directory, error: &error) as? [String] {
        var size : UInt64 = 0
        for pathComponent in contents {
            let path = directory.stringByAppendingPathComponent(pathComponent)
            if let attributes : NSDictionary = fileManager.attributesOfItemAtPath(path, error: &error) {
                size += attributes.fileSize()
            } else {
                NSLog("Failed to read file size of \(path) with error \(error)")
            }
        }
        return size
    } else {
        NSLog("Failed to list directory with error \(error)")
        return 0
    }
}

但是,通过使用if let我不能再提前返回。如果有些方法不使用提前返回而有些方法使用,那么我最终会得到一个混合编码风格的项目。

我的问题是,有没有办法以黄金路径风格编码,而无需在涉及选项时强制展开?

4

1 回答 1

0

就我个人而言,我会使用方法提取,在这种情况下,将 pathComponent 部分提取到一个单独的方法中,从而避免将概念上分离的代码混合在一起的多个缩进和笨拙的代码。

private func calculateSize_IfLet(directoryPath:String) -> UInt64 {
    var size : UInt64 = 0
    let fileManager = NSFileManager.defaultManager()
    var error : NSError?
    if let contents = fileManager.contentsOfDirectoryAtPath(directoryPath, error: &error) as? [String] {
        size = self.calculateSizeOfDirectory(directoryPath, contents:contents)
    } else {
        NSLog("Failed to list directory with error \(error)")
    }
    return size
}

private func calculateSizeOfDirectory(directoryPath:String, contents:[String]) -> UInt64 {
    var size : UInt64 = 0
    for pathComponent in contents {
        var error : NSError?
        let fileManager = NSFileManager.defaultManager()
        let path = directoryPath.stringByAppendingPathComponent(pathComponent)
        if let attributes : NSDictionary = fileManager.attributesOfItemAtPath(path, error: &error) {
            size += attributes.fileSize()
        } else {
            NSLog("Failed to read file size of \(path) with error \(error)")
        }
    }
    return size
}
于 2014-08-25T11:49:42.790 回答