3

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

Yuri
  • 53
  • 1
  • 5
  • 2
    I have tried your code on the iOS Simulator, that works fine for me. Have you tried to log `filepath`? Probably it stores file in some not expected by you place – Igor B. May 11 '16 at 15:02
  • In my case the file was placed right here: `/Users/melifaro/Library/Developer/CoreSimulator/Devices/525924EE-1C43-4341-A3BC-EF42224DB268/data/Containers/Data/Application/A4BD9D82-7AD5-488F-BF73-541DEB5FB007/lacator.plist` – Igor B. May 11 '16 at 15:05
  • 1
    You can't write to the home directory in iOS, write to the documents directory – dan May 11 '16 at 15:18
  • @Melifaro I tried to log filepath ,the file was placed: `/var/mobile/Containers/Data/Application/AE38143E-C398-4DA7-952D-4E1C903E9637/locator.plist` ,but I couldn't find the folder – Yuri May 12 '16 at 10:48
  • What do you mean by "find the folder"? – kennytm May 12 '16 at 10:52
  • @kennytm I want to find the file 'locator.plist' in my computer but failed. – Yuri May 12 '16 at 11:04
  • @Yuri the file is on your iPhone, not your computer – kennytm May 12 '16 at 11:06
  • @kennytm What can I do to make the data stored in computer while app is running on my phone? – Yuri May 12 '16 at 11:19

3 Answers3

4

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

Community
  • 1
  • 1
Igor B.
  • 2,219
  • 13
  • 17
0

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)
    }
William Hu
  • 15,423
  • 11
  • 100
  • 121
0

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)
...
vadian
  • 274,689
  • 30
  • 353
  • 361