斯威夫特的早期回归/黄金之路

时间:2014-08-25 11:17:16

标签: coding-style swift optional forced-unwrapping

我曾经在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;
}

请注意我对!contents变量使用attributes运算符的方式。

我假设过度使用!运算符会破坏期权的目的和他们带来的类型安全性。这就是我觉得上面的方法应该在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,我无法再提前返回。如果某些方法没有使用早期返回而有些方法没有,那么我最终会得到一个混合编码风格的项目。

我的问题是,有没有办法以黄金路径的方式编码而不诉诸强制解包当涉及期权?

1 个答案:

答案 0 :(得分: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
}