前言
这是Lesson 2,这一课将主要介绍如何利用NSCoder/NSKeyedArchiver将一个包含对象(object)的数组或者字典,保存到
Document/
目录下。
保存一个包含对象的数组
假设有一个数组(NSArray)objects
包含着NSData
对象。对象图(object graph)如图
为了保存全部数据,我们需要做这样的步骤:1.创建指向Document/
目录的路径(path)2.使用恰当的类来将整个数组(array)保存到步骤1
创建的路径(path)下
创建路径
可以通过定义如下这样的compute propertityactorsFilePath
来返回指向Document/
目录的路径(path)
var actorsFilePath : String { let manager = NSFileManager.defaultManager() let url = manager.URLsForDirectory(.DocumentDirectory, inDomains: .UserDomainMask).first as! NSURL return url.URLByAppendingPathComponent("objectsArray").path! }
NSKeyedArchiver
可以用这个类将整个对象图(object graph)保存到Document/
目录下。永这个类很简单,只需如下一行代码就能将数组objects
保存到相应的文件中。
NSKeyedArchiver.archiveRootObject(objects, toFile: actorsFilePath)
然后取回数值
if let array = NSKeyedUnarchiver.unarchiveObjectWithFile(actorsFilePath) as? [NSData] { objects = array }
KeyedArchiver能够保存这些类型的对象:NSArray, NSDictionary, NSDate, NSNumber, NSString, and NSData.
NSCoding
如果上面的那些类型不能满足要求。则可以通过使用Protocol NSCoding
来自定义自己喜欢类型的对象,例如下面的例子Person
NSCoding是protocol。提供下两个有用的method:
- encodeWithCoder(:)
- init(coder:)
将要保存的类扩展 为NSObject(Nobody really gave this much thought when they were archiving Objective-C classes. But now it seems a little strange. It is possible that this will go away at some point.)
并使用NSCoding protocol。
例如:定义一个类Person
class Person : NSObject, NSCoding { struct Keys { static let Name = "name" static let ProfilePath = "profile_path" static let Movies = "movies" static let ID = "id" } var name = "" var id = 0 var imagePath = "" var movies = [Movie]() init(dictionary: [String : AnyObject]) { name = dictionary[Keys.Name] as! String id = dictionary[TheMovieDB.Keys.ID] as! Int if let pathForImgage = dictionary[Keys.ProfilePath] as? String { imagePath = pathForImgage } } var image: UIImage? { get { return TheMovieDB.Caches.imageCache.imageWithIdentifier(imagePath) } set { TheMovieDB.Caches.imageCache.storeImage(image, withIdentifier: imagePath) } } // MARK: - NSCoding func encodeWithCoder(archiver: NSCoder) { // archive the information inside the Person, one property at a time archiver.encodeObject(name, forKey: Keys.Name) archiver.encodeObject(id, forKey: Keys.ID) archiver.encodeObject(imagePath, forKey: Keys.ProfilePath) archiver.encodeObject(movies, forKey: Keys.Movies) } required init(coder unarchiver: NSCoder) { super.init() // Unarchive the data, one property at a time name = unarchiver.decodeObjectForKey(Keys.Name) as! String id = unarchiver.decodeObjectForKey(Keys.ID) as! Int imagePath = unarchiver.decodeObjectForKey(Keys.ProfilePath) as! String movies = unarchiver.decodeObjectForKey(Keys.Movies) as! [Movie] } }