[ios] Swift에서 NSDocumentDirectory를 찾는 방법은 무엇입니까?

코드가있는 Documents 폴더의 경로를 얻으려고합니다.

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

그러나 Xcode는 오류를 제공합니다. Cannot convert expression's type 'AnyObject[]!' to type 'NSSearchPathDirectory'

코드에서 무엇이 잘못되었는지 이해하려고합니다.



답변

분명히 컴파일러 NSSearchPathDirectory:0는 배열 이라고 생각 하고 물론 유형을 NSSearchPathDirectory대신 기대합니다 . 분명히 유용한 오류 메시지는 아닙니다.

그러나 이유는 다음과 같습니다.

먼저 인수 이름과 유형을 혼동하고 있습니다. 함수 정의를 살펴보십시오.

func NSSearchPathForDirectoriesInDomains(
    directory: NSSearchPathDirectory,
    domainMask: NSSearchPathDomainMask,
    expandTilde: Bool) -> AnyObject[]!
  • directory그리고 domainMask당신은 유형을 사용하고 있지만, 어쨌든 기능을 생략한다 이름입니다. 그것들은 주로 방법에 사용됩니다.
  • 또한 Swift는 강력한 형식이므로 0 만 사용하면 안됩니다. 대신 열거 형 값을 사용하십시오.
  • 마지막으로 단일 경로가 아닌 배열을 반환합니다.

따라서 Swift 2.0으로 업데이트되었습니다.

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

스위프트 3

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


답변

스위프트 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
}


답변

현대적인 권장 사항은 NSString 기반 경로 대신 파일 및 디렉토리에 NSURL을 사용하는 것입니다.

여기에 이미지 설명을 입력하십시오

따라서 앱의 문서 디렉토리를 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
}

이런 종류의 응용 프로그램은 이러한 경우 응용 프로그램이 수행하는 작업에 따라 달라지기 때문에 기본적인 오류 처리 기능이 있습니다. 그러나 이것은 파일 URL과 최신 API를 사용하여 데이터베이스 URL을 반환하고 번들이없는 경우 번들에서 초기 버전을 복사하거나 오류가 발생하면 nil을 복사합니다.


답변

Xcode 8.2.1 • 스위프트 3.0.2

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

Xcode 7.1.1 • 스위프트 2.1

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


답변

일반적으로이 확장을 사용하는 것이 좋습니다.

스위프트 3.x 및 스위프트 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]
    }
}

스위프트 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 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
}

업데이트
새로운 swift 2.0에는 가드 (아날로그가 아닌 경우 루비)가 있으므로 가드를 사용하면 훨씬 짧고 읽기 쉽습니다.

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!