Yuri
Yuri

Reputation: 53

How to write an array to plist?

I want to write an array to .plist but nothing is in .plist after I call the function.

Here is my code:

override func viewDidLoad() {
        super.viewDidLoad()
        var filepath = NSHomeDirectory().stringByAppendingString("/lacator.plist")
        let array:NSArray = ["b","a","n","d"]
        array.writeToFile(filepath, atomically: true)

}

the file was placed :

/var/mobile/Containers/Data/Application/AE38143E-C398-4DA7-952D-4E1C903E9637/locator.plist

but I couldn't find the folder...

Upvotes: 3

Views: 4342

Answers (3)

vadian
vadian

Reputation: 285064

Nowadays (2019 but actually since the release of Swift 3 in 2016) it's highly recommended to use PropertyListSerialization and the URL related API of Filemanager.

First of all create a computed variable which returns the current URL to the documents directory

var documentsDirectoryURL : URL {
    return try! FileManager.default.url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: false)
}

The forced unwrapped URL is safe as the documents directory is guaranteed to exist.


Serialize the array with PropertyListSerialization and write the data to the URL

let fileURL = documentsDirectoryURL.appendingPathComponent("lacator.plist")
let array = ["b","a","n","d"]
do {
    let data = try PropertyListSerialization.data(fromPropertyList: array, format: .binary, options: 0)
    try data.write(to: fileURL)
} catch {
    print(error)
}

Or even more convenient in Swift 4+ with PropertyListEncoder if the type conforms to Encodable

do {
    let data = try PropertyListEncoder().encode(array)
...

Upvotes: 0

William Hu
William Hu

Reputation: 16149

Just the same as @lgor B.'s answer, but with swift 5.

struct JSONManager {

    private static var applicationDocumentsDirectory: String? {
        let paths = NSSearchPathForDirectoriesInDomains(FileManager.SearchPathDirectory.documentDirectory, FileManager.SearchPathDomainMask.userDomainMask, true)
        return paths.first
    }

    private static var mockDataPath: String? {
        guard let basePath = JSONManager.applicationDocumentsDirectory else {
            return .none
        }
        return basePath.appendingFormat("/yourPlistName.plist")
    }

    static func save(_ array: NSArray) {

        guard let path = mockDataPath else { return }
        array.write(toFile: path, atomically: true)

        assert(FileManager.default.fileExists(atPath: path))
    }

}

If you also want to read it, then add these two methods into JSONManager:

    static func readArray() -> NSArray? {
        guard let path = mockDataPath else { return .none }
        return NSArray(contentsOfFile: path)
    }

    static func readDicionary() -> NSDictionary? {
        guard let path = mockDataPath else { return .none }
        return NSDictionary(contentsOfFile: path)
    }

Upvotes: 0

Igor B.
Igor B.

Reputation: 2229

As @dan mentioned, you cannot write to home directory, consider writing to the document folder:

    func applicationDocumentsDirectory() -> String {
        let paths = NSSearchPathForDirectoriesInDomains(NSSearchPathDirectory.DocumentDirectory, NSSearchPathDomainMask.UserDomainMask, true)
        let basePath = paths.first ?? ""
        return basePath
    }

    let filepath = applicationDocumentsDirectory().stringByAppendingString("/lacator.plist")
    let array:NSArray = ["b","a","n","d"]
    array.writeToFile(filepath, atomically: true)

    print("Does file exist: \(NSFileManager.defaultManager().fileExistsAtPath(filepath)) at path: \(filepath)")

OUTPUT

    Does file exist: true at path: /var/mobile/Applications/2754A65C-DF1B-4B69-9FC5-A3A171D88087/Documents/lacator.plist

If you enable Documents folder access from iTunes, you can get this file from iTunes:

iTunes Documents Directory in my app

Upvotes: 4

Related Questions