設(shè)計(jì)模式開發(fā)中的備忘錄模式在iOS應(yīng)用開發(fā)中的運(yùn)用實(shí)例
何為備忘錄模式?
在響應(yīng)某些事件時(shí),應(yīng)用程序需要保存自身的狀態(tài),比如當(dāng)用戶保存文檔或程序退出時(shí)。例如,游戲退出之前,可能需要保存當(dāng)前會話的狀態(tài),如游戲等級、敵人數(shù)量、可用武器的種類等。游戲再次打開時(shí),玩家可以從離開的地方接著玩。很多時(shí)候,保存程序的狀態(tài)真的不需要什么特別巧妙的方法。任何簡單有效的方法都可以,但是同時(shí),保存信息應(yīng)該只對原始程序有意義。原始程序應(yīng)該是能夠解碼它所保存文檔中的信息的唯一實(shí)體。這就是備忘錄模式應(yīng)用于游戲、文字處理等程序的軟件設(shè)計(jì)中的方式,這些程序需要保存當(dāng)前上下文的復(fù)雜狀態(tài)的快照并在以后恢復(fù)。
備忘錄模式:在不破壞封裝的前提下,捕獲一個(gè)對象的內(nèi)部狀態(tài),并在該對象之外保存這個(gè)狀態(tài)。這樣以后就可將該對象恢復(fù)到原先的保存狀態(tài)。
何時(shí)使用備忘錄模式?
當(dāng)同時(shí)滿足以下兩個(gè)條件時(shí),應(yīng)當(dāng)考慮使用這一模式:
@:需要保存一個(gè)對象(或某部分)在某一個(gè)時(shí)刻的狀態(tài),這樣以后就可以恢復(fù)到先前的狀態(tài)。
@:用于獲取狀態(tài)的接口會暴漏實(shí)現(xiàn)的細(xì)節(jié),需要將其隱藏起來。
如何使用備忘錄模式:
在ViewController.m中增加下面的方法:
- (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.
[[NSUserDefaultsstandardUserDefaults] setInteger:currentAlbumIndex forKey:@"currentAlbumIndex"];
}
- (void)loadPreviousState
{
currentAlbumIndex = [[NSUserDefaultsstandardUserDefaults] integerForKey:@"currentAlbumIndex"];
[self showDataForAlbumAtIndex:currentAlbumIndex];
}
saveCurrentState 保存當(dāng)前的專輯索引到NSUserDefaults,NSUserDefaults是IOS提供的保存應(yīng)用設(shè)置信息和數(shù)據(jù)的地方。
loadPreviousState 加載之前保存的索引。這里其實(shí)不是備忘錄模式完整的實(shí)現(xiàn),但是你已經(jīng)了解到它了。
現(xiàn)在,在ViewController.m的viewDidLoad方法中,在scroller初始化之前增加下面的代碼:
[self loadPreviousState];
它將在應(yīng)用啟動的時(shí)候加載原先保存的狀態(tài)。但是在什么時(shí)候來保存應(yīng)用的狀態(tài)呢?你將使用通知來實(shí)現(xiàn)它。當(dāng)應(yīng)用進(jìn)入后臺的時(shí)候,IOS會發(fā)送UIApplicationDidEnterBackgroundNotification通知,你可以使用這個(gè)通知去保存狀態(tài),這是不是很方便?
在viewDidLoad中增加下面的代碼:
[[NSNotificationCenterdefaultCenter] addObserver:self selector:@selector(saveCurrentState) name:UIApplicationDidEnterBackgroundNotification object:nil];
現(xiàn)在,當(dāng)應(yīng)用進(jìn)入后臺的時(shí)候,ViewController將通過saveCurrentState方法自動保存當(dāng)前的狀態(tài)。
現(xiàn)在增加下面的代碼:
- (void)dealloc
{
[[NSNotificationCenterdefaultCenter] removeObserver:self];
}
這將確保當(dāng)ViewController被銷毀的時(shí)候移除觀察者。
構(gòu)建和運(yùn)行你的應(yīng)用,導(dǎo)航到一個(gè)專輯,然后通過Command+Shift+H(模擬器的情況下)將app發(fā)送到后臺,然后關(guān)閉app。再一次打開app,檢查原先選擇的專輯是不是被顯示在中間:
看起來專輯數(shù)據(jù)是正確的,但是中間的視圖卻沒有顯示正確的專輯。出了什么情況?這是可選方法initialViewIndexForHorizontalScroller的目的所在。因?yàn)檫@個(gè)方法沒有在委托中實(shí)現(xiàn),這樣的話初始化視圖總是第一個(gè)視圖。
為了修正這個(gè)問題,在ViewController.m中增加下面的代碼:
- (NSInteger)initialViewIndexForHorizontalScroller:(HorizontalScroller *)scroller
{
return currentAlbumIndex;
}
現(xiàn)在HorizontalScroller的第一個(gè)視圖終于設(shè)置為了currentAlbumIndex指定的視圖。這使得app在下次使用的時(shí)候還保留了上次使用的狀態(tài)。
再一次運(yùn)行你的app,和之前一樣滾動專輯,停止應(yīng)用,重啟,確保上面的問題已經(jīng)修復(fù)了:
如果你查看PersistencyManager的init方法,你將注意到專輯數(shù)據(jù)被硬編碼并且每次都要重新創(chuàng)建它們。但是更好的方式是創(chuàng)建專輯列表一次,然后存儲它們到一個(gè)文件,你怎么保存專輯數(shù)據(jù)到一個(gè)文件呢?
一個(gè)可選的方式就是循環(huán)Album的屬性,保存它們到一個(gè)plist文件中,當(dāng)它們需要的時(shí)候再重新構(gòu)建它們。這個(gè)不是一個(gè)最好的方式,因?yàn)槟阈枰ゾ帉懪c每個(gè)類的屬性關(guān)聯(lián)的特定的代碼。舉例來說如果過會你要?jiǎng)?chuàng)建一個(gè)具有不同屬性的Movie類,保存和加載的代碼需要重新寫。
此外,你也不能保存每個(gè)類的私有變量,因?yàn)樗鼈冊谕饷娴念愔惺遣豢梢姷摹_@正是蘋果創(chuàng)建了歸檔(Archiving)機(jī)制的原因。
Cocoa Touch框架中的備忘錄模式
Cocoa Touch框架在歸檔、屬性列表序列化和核心數(shù)據(jù)中采用了備忘錄模式。Cocoa的歸檔是對對象及其屬性還有同其他對象間的關(guān)系進(jìn)行編碼,形成一個(gè)文檔,該文檔既可以保存于文件系統(tǒng),也可以在進(jìn)程或網(wǎng)絡(luò)間傳送。對象與其他對象的關(guān)系被看做對象圖的網(wǎng)絡(luò)。歸檔過程把對象保存為一種與架構(gòu)無關(guān)的字節(jié)流,保持對象的標(biāo)識以及對象之間的關(guān)系。對象的類型也同數(shù)據(jù)一起保存。從字節(jié)流解碼出來的對象通常用與對象編碼時(shí)相同的類型進(jìn)行實(shí)例化。
如果想歸檔一個(gè)對象,很多時(shí)候我們是考慮保存程序的狀態(tài)。在模型-視圖-控制器范式中,程序的狀態(tài)通常由模型對象來進(jìn)行維護(hù)。我們把模型對象編碼到文檔,然后再對其解碼讀回來。在運(yùn)行時(shí)使用NSCoder對象進(jìn)行編碼與解碼操作。NSCoder本身是個(gè)抽象類。蘋果公司建議通過NSCoder的具體類NSKeyArchiver和NSKeyedUnarchiver,使用基于鍵的歸檔技術(shù)。被編碼與解碼的對象必須遵守NSCoding協(xié)議并實(shí)現(xiàn)以下方法:
- (void)encodeWithCoder:(NSCoder *)aCoder;
- (id)initWithCoder:(NSCoder *)aDecoder;
- iOS App設(shè)計(jì)模式開發(fā)中對interpreter解釋器模式的運(yùn)用
- 詳解iOS App設(shè)計(jì)模式開發(fā)中對于享元模式的運(yùn)用
- iOS App設(shè)計(jì)模式開發(fā)中對建造者模式的運(yùn)用實(shí)例
- iOS App設(shè)計(jì)模式開發(fā)中對迭代器模式的使用示例
- iOS App的設(shè)計(jì)模式開發(fā)中對State狀態(tài)模式的運(yùn)用
- 解析iOS應(yīng)用開發(fā)中對設(shè)計(jì)模式中的抽象工廠模式的實(shí)現(xiàn)
- 詳解iOS應(yīng)用開發(fā)中使用設(shè)計(jì)模式中的抽象工廠模式
- 實(shí)例解析設(shè)計(jì)模式中的外觀模式在iOS App開發(fā)中的運(yùn)用
- 深入解析設(shè)計(jì)模式中的裝飾器模式在iOS應(yīng)用開發(fā)中的實(shí)現(xiàn)
- 舉例講解設(shè)計(jì)模式中的原型模式在iOS應(yīng)用開發(fā)中的作用
相關(guān)文章
實(shí)例解析設(shè)計(jì)模式中的外觀模式在iOS App開發(fā)中的運(yùn)用
這篇文章主要介紹了設(shè)計(jì)模式中的外觀模式在iOS App開發(fā)中的運(yùn)用,實(shí)例代碼為傳統(tǒng)的Objective-C,需要的朋友可以參考下2016-03-03iOS 隱私權(quán)限和通過openURL實(shí)現(xiàn)跳轉(zhuǎn)實(shí)例
這篇文章主要介紹了iOS 隱私權(quán)限和通過openURL實(shí)現(xiàn)跳轉(zhuǎn)實(shí)例,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-06-06Flutter之PageView頁面緩存與KeepAlive
這篇文章主要為大家介紹了Flutter之PageView頁面緩存與KeepAlive示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-10-10iOS開發(fā)教程之UIRefreshControl使用的踩坑指南
UIRefreshControl是iOS6自帶的UITableView下拉刷新控件。下面這篇文章主要給大家介紹了關(guān)于iOS開發(fā)教程之UIRefreshControl使用的踩坑指南,文中通過示例代碼介紹的非常詳細(xì),需要的朋友可以參考借鑒,下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧。2018-04-04iOS開發(fā)中控制屏幕旋轉(zhuǎn)的編寫方法小結(jié)
這篇文章主要介紹了iOS開發(fā)中控制屏幕旋轉(zhuǎn)的編寫方法小結(jié),包括橫豎屏切換時(shí)視圖所出現(xiàn)的問題等經(jīng)常需要注意的地方,需要的朋友可以參考下2015-10-10