<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ??一站式輕松地調用各大LLM模型接口,支持GPT4、智譜、豆包、星火、月之暗面及文生圖、文生視頻 廣告
                備忘錄模式捕捉并且具象化一個對象的內在狀態。換句話說,它把你的對象存在了某個地方,然后在以后的某個時間再把它恢復出來,而不會打破它本身的封裝性,私有數據依舊是私有數據。 ### 如何使用備忘錄模式 在?`ViewController.swift`?里加上下面兩個方法: ~~~ //MARK: Memento Pattern func saveCurrentState() { // When the user leaves the app and then comes back again, he wants it to be in the exact same state // he left it. In order to do this we need to save the currently displayed album. // Since it's only one piece of information we can use NSUserDefaults. NSUserDefaults.standardUserDefaults().setInteger(currentAlbumIndex, forKey: "currentAlbumIndex") } func loadPreviousState() { currentAlbumIndex = NSUserDefaults.standardUserDefaults().integerForKey("currentAlbumIndex") showDataForAlbum(currentAlbumIndex) } ~~~ `saveCurrentState`?把當前相冊的索引值存到?`NSUserDefaults`?里。`NSUserDefaults`?是 iOS 提供的一個標準存儲方案,用于保存應用的配置信息和數據。 `loadPreviousState`?方法加載上次存儲的索引值。這并不是備忘錄模式的完整實現,但是已經離目標不遠了。 接下來在?`viewDidLoad`?的?`scroller.delegate = self`?前面調用: ~~~ loadPreviousState() ~~~ 這樣在剛初始化的時候就加載了上次存儲的狀態。但是什么時候存儲當前狀態呢?這個時候我們可以用通知來做。在應用進入到后臺的時候, iOS 會發送一個`UIApplicationDidEnterBackgroundNotification`?的通知,我們可以在這個通知里調用`saveCurrentState`?這個方法。是不是很方便? 在?`viewDidLoad`?的最后加上如下代碼: ~~~ NSNotificationCenter.defaultCenter().addObserver(self, selector:"saveCurrentState", name: UIApplicationDidEnterBackgroundNotification, object: nil) ~~~ 現在,當應用即將進入后臺的時候,`ViewController`?會調用?`saveCurrentState`?方法自動存儲當前狀態。 當然也別忘了取消監聽通知,添加如下代碼: ~~~ deinit { NSNotificationCenter.defaultCenter().removeObserver(self) } ~~~ 這樣就確保在?`ViewController`?銷毀的時候取消監聽通知。 這時再運行程序,隨意移到某個專輯上,然后按下 Home 鍵把應用切換到后臺,再在 Xcode 上把 App 關閉。重新啟動,會看見上次記錄的專輯已經存了下來并成功還原了: [![](http://cdn2.raywenderlich.com/wp-content/uploads/2014/11/swiftDesignPattern15-202x320.png)](http://cdn2.raywenderlich.com/wp-content/uploads/2014/11/swiftDesignPattern15-202x320.png) 看起來專輯數據好像是對了,但是上面的滾動條似乎出了問題,沒有居中啊! 這時?`initialViewIndex`?方法就派上用場了。由于在委托里 (也就是?`ViewController`?) 還沒實現這個方法,所以初始化的結果總是第一張專輯。 為了修復這個問題,我們可以在?`ViewController.swift`?里添加如下代碼: ~~~ func initialViewIndex(scroller: HorizontalScroller) -> Int { return currentAlbumIndex } ~~~ 現在?`HorizontalScroller`?可以根據?`currentAlbumIndex`?自動滑到相應的索引位置了。 再次重復上次的步驟,切到后臺,關閉應用,重啟,一切順利: [![](http://cdn2.raywenderlich.com/wp-content/uploads/2014/11/swiftDesignPattern16-230x320.png)](http://cdn2.raywenderlich.com/wp-content/uploads/2014/11/swiftDesignPattern16-230x320.png) 回頭看看?`PersistencyManager`?的?`init`?方法,你會發現專輯數據是我們硬編碼寫進去的,而且每次創建?`PersistencyManager`?的時候都會再創建一次專輯數據。而實際上一個比較好的方案是只創建一次,然后把專輯數據存到本地文件里。我們如何把專輯數據存到文件里呢? 一種方案是遍歷?`Album`?的屬性然后把它們寫到一個?`plist`?文件里,然后如果需要的時候再重新創建?`Album`?對象。這并不是最好的選擇,因為數據和屬性不同,你的代碼也就要相應的產生變化。舉個例子,如果我們以后想添加?`Movie`?對象,它有著完全不同的屬性,那么存儲和讀取數據又需要重寫新的代碼。 況且你也無法存儲這些對象的私有屬性,因為其他類是沒有訪問權限的。這也就是為什么 Apple 提供了 歸檔 的機制。 ### 歸檔 - Archiving 蘋果通過歸檔的方法來實現備忘錄模式。它把對象轉化成了流然后在不暴露內部屬性的情況下存儲數據。你可以讀一讀 《iOS 6 by Tutorials》 這本書的第 16 章,或者看下[蘋果的歸檔和序列化文檔](https://developer.apple.com/library/ios/documentation/Cocoa/Conceptual/Archiving/Archiving.html)。 #### 如何使用歸檔 首先,我們需要讓?`Album`?實現?`NSCoding`?協議,聲明這個類是可被歸檔的。打開?`Album.swift`在?`class`?那行后面加上?`NSCoding`?: ~~~ class Album: NSObject, NSCoding { ~~~ 然后添加如下的兩個方法: ~~~ required init(coder decoder: NSCoder) { super.init() self.title = decoder.decodeObjectForKey("title") as String? self.artist = decoder.decodeObjectForKey("artist") as String? self.genre = decoder.decodeObjectForKey("genre") as String? self.coverUrl = decoder.decodeObjectForKey("cover_url") as String? self.year = decoder.decodeObjectForKey("year") as String? } func encodeWithCoder(aCoder: NSCoder) { aCoder.encodeObject(title, forKey: "title") aCoder.encodeObject(artist, forKey: "artist") aCoder.encodeObject(genre, forKey: "genre") aCoder.encodeObject(coverUrl, forKey: "cover_url") aCoder.encodeObject(year, forKey: "year") } ~~~ `encodeWithCoder`?方法是?`NSCoding`?的一部分,在被歸檔的時候調用。相對的,`init(coder:)`?方法則是用來解檔的。很簡單,很強大。 現在?`Album`?對象可以被歸檔了,添加一些代碼來存儲和加載?`Album`?數據。 在?`PersistencyManager.swift`?里添加如下代碼: ~~~ func saveAlbums() { var filename = NSHomeDirectory().stringByAppendingString("/Documents/albums.bin") let data = NSKeyedArchiver.archivedDataWithRootObject(albums) data.writeToFile(filename, atomically: true) } ~~~ 這個方法可以用來存儲專輯。?`NSKeyedArchiver`?把專輯數組歸檔到了?`albums.bin`?這個文件里。 當我們歸檔一個包含子對象的對象時,系統會自動遞歸的歸檔子對象,然后是子對象的子對象,這樣一層層遞歸下去。在我們的例子里,我們歸檔的是?`albums`?因為?`Array`?和?`Album`?都是實現`NSCopying`?接口的,所以數組里的對象都可以自動歸檔。 用下面的代碼取代?`PersistencyManager`?中的?`init`?方法: ~~~ override init() { super.init() if let data = NSData(contentsOfFile: NSHomeDirectory().stringByAppendingString("/Documents/albums.bin")) { let unarchiveAlbums = NSKeyedUnarchiver.unarchiveObjectWithData(data) as [Album]? if let unwrappedAlbum = unarchiveAlbums { albums = unwrappedAlbum } } else { createPlaceholderAlbum() } } func createPlaceholderAlbum() { //Dummy list of albums let album1 = Album(title: "Best of Bowie", artist: "David Bowie", genre: "Pop", coverUrl: "http://www.coversproject.com/static/thumbs/album/album_david%20bowie_best%20of%20bowie.png", year: "1992") let album2 = Album(title: "It's My Life", artist: "No Doubt", genre: "Pop", coverUrl: "http://www.coversproject.com/static/thumbs/album/album_no%20doubt_its%20my%20life%20%20bathwater.png", year: "2003") let album3 = Album(title: "Nothing Like The Sun", artist: "Sting", genre: "Pop", coverUrl: "http://www.coversproject.com/static/thumbs/album/album_sting_nothing%20like%20the%20sun.png", year: "1999") let album4 = Album(title: "Staring at the Sun", artist: "U2", genre: "Pop", coverUrl: "http://www.coversproject.com/static/thumbs/album/album_u2_staring%20at%20the%20sun.png", year: "2000") let album5 = Album(title: "American Pie", artist: "Madonna", genre: "Pop", coverUrl: "http://www.coversproject.com/static/thumbs/album/album_madonna_american%20pie.png", year: "2000") albums = [album1, album2, album3, album4, album5] saveAlbums() } ~~~ 我們把創建專輯數據的方法放到了?`createPlaceholderAlbum`?里,這樣代碼可讀性更高。在新的代碼里,如果存在歸檔文件,?`NSKeyedUnarchiver`?從歸檔文件加載數據;否則就創建歸檔文件,這樣下次程序啟動的時候可以讀取本地文件加載數據。 我們還想在每次程序進入后臺的時候存儲專輯數據。看起來現在這個功能并不是必須的,但是如果以后我們加了編輯功能,這樣做還是很有必要的,那時我們肯定希望確保新的數據會同步到本地的歸檔文件。 因為我們的程序通過?`LibraryAPI`?來訪問所有服務,所以我們需要通過?`LibraryAPI`?來通知`PersistencyManager`?存儲專輯數據。 在?`LibraryAPI`?里添加存儲專輯數據的方法: ~~~ func saveAlbums() { persistencyManager.saveAlbums() } ~~~ 這個方法很簡單,就是把?`LibraryAPI`?的?`saveAlbums`?方法傳遞給了?`persistencyManager`?的`saveAlbums`?方法。 然后在?`ViewController.swift`?的?`saveCurrentState`?方法的最后加上: ~~~ LibraryAPI.sharedInstance.saveAlbums() ~~~ 在?`ViewController`?需要存儲狀態的時候,上面的代碼通過?`LibraryAPI`?歸檔當前的專輯數據。 運行一下程序,檢查一下沒有編譯錯誤。 不幸的是似乎沒什么簡單的方法來檢查歸檔是否正確完成。你可以檢查一下?`Documents`?目錄,看下是否存在歸檔文件。如果要查看其他數據變化的話,還需要添加編輯專輯數據的功能。 不過和編輯數據相比,似乎加個刪除專輯的功能更好一點,如果不想要這張專輯直接刪除即可。再進一步,萬一誤刪了話,是不是還可以再加個撤銷按鈕?
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看