代码之家  ›  专栏  ›  技术社区  ›  Francesco Zaffaroni

Swift 4备选方案(如果出租)

  •  1
  • Francesco Zaffaroni  · 技术社区  · 7 年前

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

    有没有办法有条件地设置 url 变量,以便我可以编写 parse(fromFile:) 方法一次,而不是在if-else中?最直观的方式似乎是 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 回复  |  直到 7 年前
        1
  •  4
  •   Sulthan    7 年前

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

    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()
    }
    
        2
  •  3
  •   Charles Srstka    7 年前

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

    如果FileManager的表达式返回nil(通过抛出,由于 try? ),然后 Bundle.main.url(...) 将改为使用。

    如果这也是零,那么条件绑定将完全失败,并且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()
    }
    
        3
  •  2
  •   GetSwifty    7 年前

    由于在前两种情况下做的是相同的事情,而在第二种情况下做的是不同的事情,因此这是其自身功能的一个很好的候选者:

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

    它很好地分离了关注点,使其在使用时越来越清晰。如果您需要对文件执行任何其他操作,您可以调用该函数,而不是复制粘贴逻辑。