如何在swift中findNSDocumentDirectory?

我正在尝试使用代码获取“文档”文件夹的path:

var documentsPath = NSSearchPathForDirectoriesInDomains(NSSearchPathDirectory:0,NSSearchPathDomainMask:0,true) 

但xcode给出错误:不能转换expression式的types'AnyObject []!' 键入“NSSearchPathDirectory”

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

显然,编译器认为NSSearchPathDirectory:0是一个数组,当然它需要typesNSSearchPathDirectory 。 当然不是一个有用的错误信息。

但至于原因:

首先,你混淆了参数名称和types。 看看函数定义:

 func NSSearchPathForDirectoriesInDomains( directory: NSSearchPathDirectory, domainMask: NSSearchPathDomainMask, expandTilde: Bool) -> AnyObject[]! 
  • directorydomainMask是名称,你正在使用的types,但你应该离开它们的function无论如何。 它们主要用于方法。
  • 此外,Swift是强types的,所以你不应该只使用0.使用枚举的值。
  • 最后,它返回一个数组,而不仅仅是一个单一的path。

所以这留给我们(更新为Swift 2.0):

 let documentsPath = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true)[0] 

和Swift 3:

 let documentsPath = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0] 

现代的build议是将NSURL用于文件和目录,而不是基于NSString的path:

在这里输入图像描述

因此,要将该应用程序的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 } 

这有一个基本的error handling,这种取决于你的应用程序将在这种情况下做什么。 但是,这使用文件URL和更现代的api来返回数据库URL,如果不存在,则将最初的版本复制出来,否则返回nil。

Xcode 8.2.1•Swift 3.0.2

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

Xcode 7.1.1•Swift 2.1

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

对于看起来和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 } 

更新我已经错过了新的迅速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 } 

更方便Swift 3方法:

 let documentsUrl = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first! 

通常我喜欢使用这个扩展名:

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

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

Swift 3.0和4.0

如果找不到path,直接从数组中获取第一个元素可能会导致exception。 所以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 } 

Xcode 8b4 Swift 3.0

 let paths = NSSearchPathForDirectoriesInDomains(FileManager.SearchPathDirectory.documentDirectory, FileManager.SearchPathDomainMask.userDomainMask, true) 

通常我喜欢下面的swift 3 ,因为我可以添加文件名和轻松创build一个文件

 let fileManager = FileManager.default if let documentsURL = fileManager.urls(for: .documentDirectory, in: .userDomainMask).first { let databasePath = documentsURL.appendingPathComponent("db.sqlite3").path print("directory path:", documentsURL.path) print("database path:", databasePath) if !fileManager.fileExists(atPath: databasePath) { fileManager.createFile(atPath: databasePath, contents: nil, attributes: nil) } }