Early return/golden path in Swift

╄→гoц情女王★ 提交于 2019-12-07 11:14:48

问题


I'm used to write code with early return/golden path in Objective-C. I tried this approach in Swift, and noticed that early return comes at the expense of using the forced unwrapping operator (!) when optionals are involved.

Take a method that calculates the size of a directory. First, the golden path version:

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;
}

Notice how I'm using the ! operator both for the contents and attributes variables.

I'm assuming that overusing the ! operator kind of defeats the purpose of optionals and the type safety they bring. This is how I feel the above method should be coded in Swift to avoid forced unwrapping:

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
    }
}

However, by using if let I can't do early return anymore. If some methods don't use early return and some do, then I end up with a project with mixed coding style.

My question is, is there a way to code in golden path style without resorting to forced unwrapping when optionals are involved?


回答1:


Personally I would use extraction of methods, in this case extract the pathComponent section into a separate method thus avoiding the multiple indent and awkward code that mashes conceptually separate code together.

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
}


来源:https://stackoverflow.com/questions/25484718/early-return-golden-path-in-swift

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!