ios - tutorial - Comment trouver NSDocumentDirectory dans swift?




the swift programming language pdf (6)

J'essaie d'obtenir le chemin d'accès au dossier Documents avec du code:

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

mais xcode donne une erreur: Impossible de convertir le type de l'expression 'AnyObject []!' taper 'NSSearchPathDirectory'

J'essaie de comprendre ce qui ne va pas dans le code?


Apparemment, le compilateur pense NSSearchPathDirectory:0 est un tableau, et bien sûr il attend le type NSSearchPathDirectory place. Certainement pas un message d'erreur utile.

Mais quant aux raisons:

D'abord, vous confondez les noms et les types d'arguments. Jetez un oeil à la définition de la fonction:

func NSSearchPathForDirectoriesInDomains(
    directory: NSSearchPathDirectory,
    domainMask: NSSearchPathDomainMask,
    expandTilde: Bool) -> AnyObject[]!
  • directory et domainMask sont les noms, vous utilisez les types, mais vous devriez les laisser de toute façon pour les fonctions. Ils sont utilisés principalement dans les méthodes.
  • En outre, Swift est fortement typé, donc vous ne devriez pas utiliser simplement 0. Utilisez plutôt la valeur d'enum.
  • Et enfin, il retourne un tableau, pas seulement un seul chemin.

Alors ça nous laisse avec (mis à jour pour Swift 2.0):

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

et pour Swift 3:

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

Habituellement je préfère comme ci-dessous dans 3 rapide , parce que je peux ajouter le nom de fichier et créer un fichier facilement

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

La recommandation moderne est d'utiliser NSURLs pour les fichiers et les répertoires au lieu de chemins basés sur NSString:

Donc, pour obtenir le répertoire de documents pour l'application en tant que 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
}

Cela a une gestion d'erreur rudimentaire, car cela dépend de ce que votre application va faire dans de tels cas. Mais cela utilise des URLs de fichiers et une API plus moderne pour renvoyer l'URL de la base de données, en copiant la version initiale hors de l'ensemble si elle n'existe pas déjà, ou une valeur nulle en cas d'erreur.


Méthode Swift 3 plus pratique:

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

Swift 3.0 et 4.0

Obtenir directement le premier élément d'un tableau peut provoquer une exception si le chemin n'est pas trouvé. Donc appeler d' first , puis déballer est la meilleure solution

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