你好,歡迎來到IOS教程網

 Ios教程網 >> IOS編程開發 >> IOS開發綜合 >> IOS設計模式第九篇之備忘錄模式

IOS設計模式第九篇之備忘錄模式

編輯:IOS開發綜合
備忘錄模式捕獲和具體化對象的內部狀態。換句話說,它可以節省你的東西後來,這種外部狀態可以恢復在不違反封裝;   也就是說,私人數據是私有的。   怎麼用備忘錄設計模式   在Viewcontroller的實現文件裡添加下面方法:   - (void)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"];   }   - (void)loadPreviousState   {       currentAlbumIndex = [[NSUserDefaults standardUserDefaults] integerForKey:@"currentAlbumIndex"];       [self showDataForAlbumAtIndex:currentAlbumIndex];   }   saveCurrentState 保存了這個當前專輯的索引用NSUserDefaults 他是一個蘋果提供的標准的存儲應用設置和數據的。   loadPreviousState 加載之前保存的索引。這不是備忘錄設計模式的完全實現。   現在添加代碼在滑動視圖初始化前面:   [self loadPreviousState];   應用程序啟動時加載以前保存的狀態,但是你保存應用當前轉台只是為了加載?你將要用通知做這件事。當應用進入到後台系統發送   UIApplicationDidEnterBackgroundNotification。你可以用這個通知調用saveCurrentState。這不是很方面嗎?   在ViewDidLoad添加下面代碼:   [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(saveCurrentState) name:UIApplicationDidEnterBackgroundNotification object:nil];   現在這個應用進入到後台。將要自動的調用saveCurrentState方法來保存當前狀態。   現在添加下面代碼:   - (void)dealloc   {       [[NSNotificationCenter defaultCenter] removeObserver:self];   }   這個保證你Viewcontroller銷毀的時候移除這個類注冊的觀察者。   構建和運行您的應用程序。導航到一個專輯,將應用程序發送到後台使用命令+ Shift + H(如果你是在模擬器),然後關閉應用程序,重新啟動,並檢查之前,選擇專輯為中心:   看起來你的專輯數據是正確的。但是你的滑動視圖沒有在中間這是怎麼了?   這就是上面可選協議方法的意義   initialViewIndexForHorizontalScroller:因為這個方法在代理類裡面沒有實現。在這個例子代理類就是Viewcontroller,因此初始視圖一直被設置為第一個視圖。   為了修正他在Viewcontroller的實現文件裡面添加下面代碼:   - (NSInteger)initialViewIndexForHorizontalScroller:(HorizontalScroller *)scroller   {       return currentAlbumIndex;   }   現在這個滑動視圖的第一個視圖可以設置為任何專輯是由   currentAlbumIndex表明的。這是一個很好的方法來確保你的應用體驗來維持私有和可恢復的。   如果你看看PersistencyManager的init,你將要注意到這個專輯數據是硬件編碼並且PersistencyManager創建的時候都會重新創建。最好的解決方法是一旦創建專輯列表就把他們存儲到一個文件。那麼怎麼把專輯存儲到文件呢?   一種方法是迭代專輯的屬性,保存他們到一個plist文件並且然後創建專輯的實例一旦需要的時候。但是這不是最佳選擇,由於需要你編寫特定的代碼依靠每個類的屬性和數據。例如你接下來創建的movies類有不同的屬性,保存和加載數據需要新的代碼。   此外,你不能保存每個類的實例的私有變量,因為他們無法訪問外部類。這就是為什麼蘋果公司創建歸檔機制。   歸檔   蘋果的一個專門記憶模式的實現是歸檔。把一個對象轉化為流便於保存和恢復不用向外部類暴露私有的屬性。你可以參考Apple’s Archives and Serializations Programming Guide.   那麼怎麼用歸檔呢?   首先你需要聲明專輯通過符合NSCoding協議是可以歸檔的。在專輯頭文件寫上符合NSCoding協議:   @interface Album : NSObject <NSCoding>   在實現文件裡面:   添加兩個方法:   - (void)encodeWithCoder:(NSCoder *)aCoder   {       [aCoder encodeObject:self.year forKey:@"year"];       [aCoder encodeObject:self.title forKey:@"album"];       [aCoder encodeObject:self.artist forKey:@"artist"];       [aCoder encodeObject:self.coverUrl forKey:@"cover_url"];       [aCoder encodeObject:self.genre forKey:@"genre"];   }   - (id)initWithCoder:(NSCoder *)aDecoder   {       self = [super init];       if (self)       {           _year = [aDecoder decodeObjectForKey:@"year"];           _title = [aDecoder decodeObjectForKey:@"album"];           _artist = [aDecoder decodeObjectForKey:@"artist"];           _coverUrl = [aDecoder decodeObjectForKey:@"cover_url"];           _genre = [aDecoder decodeObjectForKey:@"genre"];       }       return self;   }   你調用encodeWithCoder:當你歸檔你類的一個實例時候,   相反地的當你解檔一個實例來創建一個專輯的實例。看著簡單而且強大。現在專輯類可以被歸檔了。   添加的代碼實際上保存和加載相冊的列表。   添加以下簽名(或方法原型)PersistencyManager.h:   這將是叫的方法保存相冊。   現在,添加PersistencyManager.m方法實現:   - (void)saveAlbums   {   NSString *filename = [NSHomeDirectory() stringByAppendingString:@"/Documents/albums.bin"];   NSData *data = [NSKeyedArchiver archivedDataWithRootObject:albums];       [data writeToFile:filename atomically:YES];   }   NSKeyedArchiver檔案專輯數組名為albums.bin的文件。   當你歸檔對象包含其他對象,   歸檔器會自動的迭代歸檔子對象並且孩子的任何子對象。   在此情況下開始對專輯類歸檔,這是專輯實例的一個數組,因此數組和專輯都支持NSCoding接口。任何在數組裡面的東西都會被歸檔。   現在在   PersistencyManager.m init方法裡添加下面代碼:   - (id)init   {       self = [super init];       if (self) {   NSData *data = [NSData dataWithContentsOfFile:[NSHomeDirectory() stringByAppendingString:@"/Documents/albums.bin"]];           albums = [NSKeyedUnarchiver unarchiveObjectWithData:data];           if (albums == nil)           {               albums = [NSMutableArray arrayWithArray:                       @[[[Album alloc] initWithTitle:@"Best of Bowie" artist:@"David Bowie" coverUrl:@"http://www.coversproject.com/static/thumbs/album/album_david%20bowie_best%20of%20bowie.png" year:@"1992"],                       [[Album alloc] initWithTitle:@"It's My Life" artist:@"No Doubt" coverUrl:@"http://www.coversproject.com/static/thumbs/album/album_no%20doubt_its%20my%20life%20%20bathwater.png" year:@"2003"],                       [[Album alloc] initWithTitle:@"Nothing Like The Sun" artist:@"Sting" coverUrl:@"http://www.coversproject.com/static/thumbs/album/album_sting_nothing%20like%20the%20sun.png" year:@"1999"],                       [[Album alloc] initWithTitle:@"Staring at the Sun" artist:@"U2" coverUrl:@"http://www.coversproject.com/static/thumbs/album/album_u2_staring%20at%20the%20sun.png" year:@"2000"],                       [[Album alloc] initWithTitle:@"American Pie" artist:@"Madonna" coverUrl:@"http://www.coversproject.com/static/thumbs/album/album_madonna_american%20pie.png" year:@"2000"]]];               [self saveAlbums];           }       }       return self;   }   在新的代碼裡,   NSKeyedUnarchiver 從文件裡面加載新的專輯數據,如果他存在。如果他不存在,   立即創建相冊數據和保存它在下次加載應用程序。   你還想保存這張專輯每次應用程序進入後台數據。   這可能不是必要的,但如果你後來添加的選項更改相冊數據   那麼你想要確保您已經保存了所有更改。   添加以下LibraryAPI.h方法簽名:   - (void)saveAlbums;   應用通過libraryAPI訪問所有的服務,這就是應用怎麼讓PersitencyManager 知道他需要保存專輯的數據。   現在添加這個方法實現到libraryAPI實現文件裡:   - (void)saveAlbums   {       [persistencyManager saveAlbums];   }   這段代碼僅僅通過在調用LibraryAPI保存相冊到PersistencyMangaer   。和上面的代碼使用LibraryAPI觸發保存專輯的數據每當Viewcontroller保存其狀態。   編譯運行你的應用檢查是不是所有東西運行正常。   不幸的是,沒有簡單的方法來檢查數據持久性是正確的。幸運的是你可以在finder裡檢查模擬器的document文件夾看專輯的數據文件是不是被創建,但是為了檢查是不是有改變你不得不添加改變專輯數據的功能。   但是代替改變數據,如果你添加一個選項來刪除你的專輯當你不想要的時候。此外你應該有一個撤銷的選項一旦你誤刪了專輯。    
  1. 上一頁:
  2. 下一頁:
蘋果刷機越獄教程| IOS教程問題解答| IOS技巧綜合| IOS7技巧| IOS8教程
Copyright © Ios教程網 All Rights Reserved