前面学了如何建立存储文件的地址。下面学习如何保存文件。
首先复制主程序ChecklistsViewController中的代码。
func saveChecklistItems()
{
let data = NSMutableData()
// 初始化。NSData creates static data objects, and NSMutableData creates dynamic data objects. NSData and NSMutableData are typically used for data storage.
let archiver = NSKeyedArchiver(forWritingWithMutableData: data)
//NSKeyedArchiver: a concrete subclass of NSCoder, provides a way to encode objects (and scalar values) into an architecture-independent format that can be stored in a file.A keyed archive differs from a non-keyed archive in that all the objects and values encoded into the archive are given names, or keys. When decoding a non-keyed archive, values have to be decoded in the same order in which they were encoded. When decoding a keyed archive, because values are requested by name, values can be decoded out of sequence or not at all.
archiver.encodeObject(items, forKey: "ChecklistItems")
//Encodes a given object and associates it with a given key.
//items:The value to encode.
//"ChecklistItems":the key.key必须是String
archiver.finishEncoding()
//Instructs the receiver to construct the final data stream.
data.writeToFile(dataFilePath(), atomically: true)
// If YES, the array is written to an auxiliary file, and then the auxiliary file is renamed to path. If NO, the array is written directly to path.
}
这是存储ChelistItems的函数。首先let data = NSMutableData()。这是在初始化,NSData()函数创建静态的数据,要创建能动态读写的数据需要用NSMutableData()。
第二行,let archiver = NSKeyedArchiver(forWritingWithMutableData: data),NSKeyedArchiver给数据赋予key。每个数据都对应于一个key,When decoding a keyed archive, because values are requested by name, values can be decoded out of sequence or not at all.
第三行,archiver.encodeObject(items, forKey: "ChecklistItems"),Encodes a given object and associates it with a given key. 其它代码的意思见备注。encodeObject和finishEncoding都是NSKeyedArchiver下面的函数。
定义了saveChecklistItems之后,在每一次更改Items的时候,就需要调用这个函数。
这里涉及一个问题,You asked NSKeyedArchiver to encode the array of items, so it not only has to encode the array itself but also each ChecklistItem object inside that array. 就是说,NSKeyedArchiver对Items编码,但是每个Items都还有自己的属性,即定义在ChecklistItem的属性text和超checked。所以,我们还需要在ChecklistItem声明协议:
class ChecklistItem:NSObject, NSCoding
// The NSCoding protocol declares the two methods that a class must implement so that instances of that class can be encoded and decoded.
//Any object class that should be codable must adopt the NSCoding protocol and implement its methods.
// 所有要被encodeWithCoder: or initWithCoder:. encodeWithCoder: 作用的地方,都要声明protocol NSCoding
{
...
}
NSCoding下面包含两个函数,encodeWithCoder: 和 initWithCoder:. encodeWithCoder: 。在ChecklistItem中我们要用到encodeWithCoder:
func encodeWithCoder(aCoder: NSCoder)
// Encodes the receiver using a given archiver.
{
aCoder.encodeObject(text, forKey: "text")
//Encodes the object objv and associates it with the string key.
aCoder.encodeBool(checked, forKey: "Checked")
}
// Swift requires that you always implement all the required methods from a protocol and NSCoding has two methods, one for saving and one for loading.
required init?(coder aDecoder: NSCoder)
{
super.init()
}
同时,我们也写了required init?(coder aDecoder: NSCoder),因为有NSCoding声明的地方,它的两个函数都需要被调用程序才能执行。