首先,我们需要让 实现 NSCoding 协议,声明这个类是可被归档的。打开 Album.swiftclass 那行后面加上 NSCoding

    然后添加如下的两个方法:

    1. required init(coder decoder: NSCoder) {
    2. super.init()
    3. self.title = decoder.decodeObjectForKey("title") as! String
    4. self.artist = decoder.decodeObjectForKey("artist")as! String
    5. self.genre = decoder.decodeObjectForKey("genre") as! String?
    6. self.coverUrl = decoder.decodeObjectForKey("cover_url")as! String
    7. self.year = decoder.decodeObjectForKey("year") as! String
    8. }
    9. func encodeWithCoder(aCoder: NSCoder) {
    10. aCoder.encodeObject(title, forKey: "title")
    11. aCoder.encodeObject(artist, forKey: "artist")
    12. aCoder.encodeObject(genre, forKey: "genre")
    13. aCoder.encodeObject(coverUrl, forKey: "cover_url")
    14. aCoder.encodeObject(year, forKey: "year")
    15. }

    encodeWithCoder 方法是 NSCoding 的一部分,在被归档的时候调用。相对的, init(coder:) 方法则是用来解档的。很简单,很强大。

    现在 Album 对象可以被归档了,添加一些代码来存储和加载 Album 数据。

    PersistencyManager.swift 里添加如下代码:

    当我们归档一个包含子对象的对象时,系统会自动递归的归档子对象,然后是子对象的子对象,这样一层层递归下去。在我们的例子里,我们归档的是 albums 因为 ArrayAlbum 都是实现 接口的,所以数组里的对象都可以自动归档。

    用下面的代码取代 PersistencyManager 中的 init 方法:

    1. override init() {
    2. super.init()
    3. if let data = NSData(contentsOfFile: NSHomeDirectory().stringByAppendingString("/Documents/albums.bin")) {
    4. let unarchiveAlbums = NSKeyedUnarchiver.unarchiveObjectWithData(data) as! [Album]
    5. albums = unwrappedAlbum
    6. }
    7. } else {
    8. createPlaceholderAlbum()
    9. }
    10. }
    11. func createPlaceholderAlbum() {
    12. //Dummy list of albums
    13. let album1 = Album(title: "Best of Bowie",
    14. artist: "David Bowie",
    15. genre: "Pop",
    16. coverUrl: "http://www.coversproject.com/static/thumbs/album/album_david%20bowie_best%20of%20bowie.png",
    17. year: "1992")
    18. let album2 = Album(title: "It's My Life",
    19. artist: "No Doubt",
    20. genre: "Pop",
    21. coverUrl: "http://www.coversproject.com/static/thumbs/album/album_no%20doubt_its%20my%20life%20%20bathwater.png",
    22. year: "2003")
    23. artist: "Sting",
    24. genre: "Pop",
    25. year: "1999")
    26. let album4 = Album(title: "Staring at the Sun",
    27. artist: "U2",
    28. genre: "Pop",
    29. coverUrl: "http://www.coversproject.com/static/thumbs/album/album_u2_staring%20at%20the%20sun.png",
    30. year: "2000")
    31. let album5 = Album(title: "American Pie",
    32. artist: "Madonna",
    33. genre: "Pop",
    34. coverUrl: "http://www.coversproject.com/static/thumbs/album/album_madonna_american%20pie.png",
    35. year: "2000")
    36. albums = [album1, album2, album3, album4, album5]
    37. saveAlbums()
    38. }

    我们把创建专辑数据的方法放到了 createPlaceholderAlbum 里,这样代码可读性更高。在新的代码里,如果存在归档文件, NSKeyedUnarchiver 从归档文件加载数据;否则就创建归档文件,这样下次程序启动的时候可以读取本地文件加载数据。

    我们还想在每次程序进入后台的时候存储专辑数据。看起来现在这个功能并不是必须的,但是如果以后我们加了编辑功能,这样做还是很有必要的,那时我们肯定希望确保新的数据会同步到本地的归档文件。

    因为我们的程序通过 LibraryAPI 来访问所有服务,所以我们需要通过 LibraryAPI 来通知 PersistencyManager 存储专辑数据。

    这个方法很简单,就是把 LibraryAPIsaveAlbums 方法传递给了 persistencyManagersaveAlbums 方法。

    然后在 ViewController.swiftsaveCurrentState 方法的最后加上:

    1. LibraryAPI.sharedInstance.saveAlbums()

    ViewController 需要存储状态的时候,上面的代码通过 LibraryAPI 归档当前的专辑数据。

    运行一下程序,检查一下没有编译错误。

    不幸的是似乎没什么简单的方法来检查归档是否正确完成。你可以检查一下 目录,看下是否存在归档文件。如果要查看其他数据变化的话,还需要添加编辑专辑数据的功能。

    完成到这一步的Demo: