如何在Swift中找到NSDocumentDirectory?

Iva*_*n R 159 ios nsdocumentdirectory swift

我正在尝试使用代码获取Documents文件夹的路径:

var documentsPath = NSSearchPathForDirectoriesInDomains(NSSearchPathDirectory:0,NSSearchPathDomainMask:0,true)
Run Code Online (Sandbox Code Playgroud)

但Xcode给出了错误: Cannot convert expression's type 'AnyObject[]!' to type 'NSSearchPathDirectory'

我试图了解代码中的错误.

nsc*_*hum 254

显然,编译器认为NSSearchPathDirectory:0是一个数组,当然它期望类型NSSearchPathDirectory.当然不是一个有用的错误消息.

但至于原因:

首先,您会混淆参数名称和类型.看一下函数定义:

func NSSearchPathForDirectoriesInDomains(
    directory: NSSearchPathDirectory,
    domainMask: NSSearchPathDomainMask,
    expandTilde: Bool) -> AnyObject[]!
Run Code Online (Sandbox Code Playgroud)
  • directory并且domainMask是名称,您使用的是类型,但是无论如何都应该将它们留给函数.它们主要用于方法.
  • 此外,Swift是强类型的,所以你不应该只使用0.使用枚举的值代替.
  • 最后,它返回一个数组,而不仅仅是一个路径.

这样就离开了我们(为Swift 2.0更新):

let documentsPath = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true)[0]
Run Code Online (Sandbox Code Playgroud)

对于Swift 3:

let documentsPath = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0]
Run Code Online (Sandbox Code Playgroud)

  • 再次运行应用程序生成一个不同的路径,为什么?:( 1)`/ var/mobile/Containers/Data/Application/9E18A573-6429-434D-9B42-08642B643970/Documents`(2)`/ var/mobile/Containers /数据/应用/ 77C8EA95-B77A-474D-8522-1F24F854A291/Documents` (3认同)

Fan*_*ing 36

Swift 3.0和4.0

如果找不到路径,直接从数组中获取第一个元素可能会导致异常.所以调用first然后解包是更好的解决方案

if let documentsPathString = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true).first {
    //This gives you the string formed path
}

if let documentsPathURL = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first {
    //This gives you the URL of the path
}
Run Code Online (Sandbox Code Playgroud)


Abi*_*ern 32

现代建议使用NSURLs代替基于NSString的路径的文件和目录:

在此输入图像描述

因此,要将应用程序的Document目录作为NSURL获取:

func databaseURL() -> NSURL? {

    let fileManager = NSFileManager.defaultManager()

    let urls = fileManager.URLsForDirectory(.DocumentDirectory, inDomains: .UserDomainMask)

    if let documentDirectory: NSURL = urls.first as? NSURL {
        // This is where the database should be in the documents directory
        let finalDatabaseURL = documentDirectory.URLByAppendingPathComponent("items.db")

        if finalDatabaseURL.checkResourceIsReachableAndReturnError(nil) {
            // The file already exists, so just return the URL
            return finalDatabaseURL
        } else {
            // Copy the initial file from the application bundle to the documents directory
            if let bundleURL = NSBundle.mainBundle().URLForResource("items", withExtension: "db") {
                let success = fileManager.copyItemAtURL(bundleURL, toURL: finalDatabaseURL, error: nil)
                if success {
                    return finalDatabaseURL
                } else {
                    println("Couldn't copy file to final location!")
                }
            } else {
                println("Couldn't find initial database in the bundle!")
            }
        }
    } else {
        println("Couldn't get documents directory!")
    }

    return nil
}
Run Code Online (Sandbox Code Playgroud)

这有一个基本的错误处理,因为这取决于你的应用程序在这种情况下会做什么.但是这会使用文件URL和更现代的api来返回数据库URL,如果它不存在则将初始版本复制到bundle之外,或者在出现错误时将其复制为nil.


Leo*_*bus 24

Xcode 8.2.1•Swift 3.0.2

let documentDirectoryURL =  try! FileManager.default.url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: true)
Run Code Online (Sandbox Code Playgroud)

Xcode 7.1.1•Swift 2.1

let documentDirectoryURL =  try! NSFileManager.defaultManager().URLForDirectory(.DocumentDirectory, inDomain: .UserDomainMask, appropriateForURL: nil, create: true)
Run Code Online (Sandbox Code Playgroud)


Ale*_*ano 20

通常我会首先使用此扩展名:

Swift 3.x和Swift 4.0:

extension FileManager {
    class func documentsDir() -> String {
        var paths = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true) as [String]
        return paths[0]
    }

    class func cachesDir() -> String {
        var paths = NSSearchPathForDirectoriesInDomains(.cachesDirectory, .userDomainMask, true) as [String]
        return paths[0]
    }
}
Run Code Online (Sandbox Code Playgroud)

Swift 2.x:

extension NSFileManager {
    class func documentsDir() -> String {
        var paths = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true) as [String]
        return paths[0]
    }

    class func cachesDir() -> String {
        var paths = NSSearchPathForDirectoriesInDomains(.CachesDirectory, .UserDomainMask, true) as [String]
        return paths[0]
    }
}
Run Code Online (Sandbox Code Playgroud)


Rom*_*fin 14

对于看起来与Swift 2.2一起使用的示例的每个人,使用现代的Abizern代码尝试捕获错误句柄

func databaseURL() -> NSURL? {

    let fileManager = NSFileManager.defaultManager()

    let urls = fileManager.URLsForDirectory(.DocumentDirectory, inDomains: .UserDomainMask)

    if let documentDirectory:NSURL = urls.first { // No use of as? NSURL because let urls returns array of NSURL
        // This is where the database should be in the documents directory
        let finalDatabaseURL = documentDirectory.URLByAppendingPathComponent("OurFile.plist")

        if finalDatabaseURL.checkResourceIsReachableAndReturnError(nil) {
            // The file already exists, so just return the URL
            return finalDatabaseURL
        } else {
            // Copy the initial file from the application bundle to the documents directory
            if let bundleURL = NSBundle.mainBundle().URLForResource("OurFile", withExtension: "plist") {

                do {
                    try fileManager.copyItemAtURL(bundleURL, toURL: finalDatabaseURL)
                } catch let error as NSError  {// Handle the error
                    print("Couldn't copy file to final location! Error:\(error.localisedDescription)")
                }

            } else {
                print("Couldn't find initial database in the bundle!")
            }
        }
    } else {
        print("Couldn't get documents directory!")
    }

    return nil
}
Run Code Online (Sandbox Code Playgroud)

更新 我错过了新的swift 2.0有防范(Ruby除非是模拟),所以有了防范它更短更可读

func databaseURL() -> NSURL? {

let fileManager = NSFileManager.defaultManager()
let urls = fileManager.URLsForDirectory(.DocumentDirectory, inDomains: .UserDomainMask)

// If array of path is empty the document folder not found
guard urls.count != 0 else {
    return nil
}

let finalDatabaseURL = urls.first!.URLByAppendingPathComponent("OurFile.plist")
// Check if file reachable, and if reacheble just return path
guard finalDatabaseURL.checkResourceIsReachableAndReturnError(nil) else {
    // Check if file is exists in bundle folder
    if let bundleURL = NSBundle.mainBundle().URLForResource("OurFile", withExtension: "plist") {
        // if exist we will copy it
        do {
            try fileManager.copyItemAtURL(bundleURL, toURL: finalDatabaseURL)
        } catch let error as NSError { // Handle the error
            print("File copy failed! Error:\(error.localizedDescription)")
        }
    } else {
        print("Our file not exist in bundle folder")
        return nil
    }
    return finalDatabaseURL
}
return finalDatabaseURL 
}
Run Code Online (Sandbox Code Playgroud)


And*_*eev 11

更方便的Swift 3方法:

let documentsUrl = FileManager.default.urls(for: .documentDirectory, 
                                             in: .userDomainMask).first!
Run Code Online (Sandbox Code Playgroud)

  • 我不认为每次我们想要获取Documents目录的URL时都需要实例化一个新的文件管理器. (6认同)

Sia*_*Alp 5

Xcode 8b4 Swift 3.0

let paths = NSSearchPathForDirectoriesInDomains(FileManager.SearchPathDirectory.documentDirectory, FileManager.SearchPathDomainMask.userDomainMask, true)
Run Code Online (Sandbox Code Playgroud)