Similar to how a game allows you to save your progress, I have an application in iOS that stores a user's progress in a single array. I would like to store that array to a file so that when the user reopens their app this file loads their current status.
-
agreed thanks for the clarifying question. I have updated the question to target iOS. – Alex Bailey Jan 04 '17 at 16:03
-
1No, do not add your technologies to the title. That's what the tags are for. – Léo Natan Jan 04 '17 at 16:18
-
Questions that ask for the "best" way are generally opinion-based, if not too broad. – JAL Jan 04 '17 at 16:18
-
1@JAL Not necessarily. Nothing wrong with asking for best practices *in principle*. – Léo Natan Jan 04 '17 at 16:19
-
@LeoNatan I disagree. The question can be reworded to not focus on a "best way," but questions like these are off-topic, either POB or too broad. In this case I believe that this question is too broad. http://meta.stackoverflow.com/q/265928/2415822 – JAL Jan 04 '17 at 16:21
-
Also this is a duplicate of many older questions: http://stackoverflow.com/q/1487606/2415822, http://stackoverflow.com/q/5413851/2415822, http://stackoverflow.com/q/26233067/2415822, etc. Just use google. – JAL Jan 04 '17 at 16:23
-
@JAL I didn't find anything specific to swift 3 thus the question here. – Alex Bailey Jan 04 '17 at 16:32
2 Answers
The easiest way is to use a NSKeyedArchiver
/NSKeyedUnarchiver
pair and be sure each of the objects in the array is conforming to NSCoding
. You could read here about it.
NSKeyedArchiver.archiveRootObject(myArray, toFile: filePath)
and then unarchiving
if let array = NSKeyedUnarchiver.unarchiveObjectWithFile(filePath) as? [Any] {
objects = array
}
Here is an example object conforming to NSCoding
(taken from the article linked above):
class Person : NSObject, NSCoding {
struct Keys {
static let Name = "name"
static let Age = "age"
}
var name = ""
var age = 0
init(dictionary: [String : AnyObject]) {
name = dictionary[Keys.Name] as! String
age = dictionary[Keys.Age] as! Int
}
public func encode(with archiver: NSCoder) {
archiver.encodeObject(name, forKey: Keys.Name)
archiver.encodeObject(age, forKey: Keys.Age)
}
required init(coder unarchiver: NSCoder) {
super.init()
name = unarchiver.decodeObjectForKey(Keys.Name) as! String
age = unarchiver.decodeObjectForKey(Keys.Age) as! Int
}
}

- 793
- 9
- 20

- 3,856
- 26
- 38
-
You don't need `NSKeyedArchiver` to store a normal array into `NSUserDefaults`, you only need it if its an array of custom objects. – Rikh Jan 04 '17 at 16:10
-
@Rikh: yes, but this is the most general case, I assume the game state in any non-trivial app would use some kind of custom objects. – Bogdan Farca Jan 04 '17 at 16:12
-
@Rikh, You can only save an array to user defaults if all the objects are property list objects, as mentioned in my answer. There are a LOT of types of system objects that are not custom, but are not in the very short list of property list objects. – Duncan C Jan 04 '17 at 16:13
-
@Rikh, also note that the OP asked about saving an array to a file, not saving to NSUserDefaults. – Duncan C Jan 04 '17 at 16:15
-
Ah my mistake then! I had no idea about system objects! I assumed incorrectly that you would normally use either property list objects or models! – Rikh Jan 04 '17 at 16:16
If the objects in your array are all "property list objects" (dictionaries, arrays, strings, numbers (integer and float), dates, binary data, and Boolean values) then you could use the array method write(toFile:atomically:)
to save your array to a file, and then reload the resulting file with arrayWithContentsOfFile:
or init(contentsOfFile:)
.
If you have objects in your array's object graph
that are not property list objects then that approach won't work. In that case, @BogdanFarca's suggestion of using NSKeyedArchiver
/NSKeyedUnarchiver
would be a good way to go.

- 128,072
- 22
- 173
- 272
-
This sounds like the right way to go. I've been searching for a clear example of how to do this for an array in Swift 3.0 but haven't found anything. Can you point me to a working example of how to do this? – Alex Bailey Jan 04 '17 at 16:17
-
1It's one line of code. `array.write(toFile: path, atomically: true)`. The path needs to point to a directory that you are allowed to write to, like the documents directory. – Duncan C Jan 04 '17 at 16:28