UI狀態(tài)保存和恢復(fù)(三)

UI狀態(tài)保存和恢復(fù)(三)

前面兩篇我們介紹了UI狀態(tài)保存和恢復(fù)的流程哨坪,UIStateRestoration協(xié)議類(lèi)的方法,適用場(chǎng)景乍楚,調(diào)試策略当编,UIApplication,UIViewController,UIView關(guān)于UIStateRestoration協(xié)議所提供的接口方法以及如何實(shí)現(xiàn)UI狀態(tài)保存和恢復(fù)。本篇我們將介紹UIStateRestoration協(xié)議類(lèi)中的UIDataSourceModelAssociation協(xié)議徒溪。

關(guān)于UIDataSourceModelAssociation協(xié)議

引用官網(wǎng)的解釋

Your data source objects can adopt this protocol to assist a corresponding table or collection view during the state restoration process. Those classes use the methods of this protocol to ensure that the same data objects (and not just the same row indexes) are scrolled into view and selected.
//你的數(shù)據(jù)源對(duì)象可以實(shí)現(xiàn)這個(gè)協(xié)議忿偷,在狀態(tài)恢復(fù)的過(guò)程中去支持相關(guān)的table or collection view;這些實(shí)現(xiàn)了該協(xié)議的類(lèi)臊泌,使用這個(gè)協(xié)議的方法去保證相同的數(shù)據(jù)對(duì)象鲤桥,(而不僅僅是相同的行的索引)被滾動(dòng)到視圖并且被選中。
Before you can implement this protocol, your app must be able to identify data objects consistently between app launches. This requires being able to take some identifying marker of the object and convert that marker into a string that can then be saved with the rest of the app state. For example, a Core Data app could convert a managed object’s ID into a URI that it could then convert into a string.
//在你實(shí)現(xiàn)這個(gè)協(xié)議之前渠概,你的App必須能夠在App啟動(dòng)之間茶凳,一直(總是可以)辨別出數(shù)據(jù)源對(duì)象。這就要求對(duì)象能夠有一些辨認(rèn)標(biāo)識(shí)高氮,并且可以把標(biāo)識(shí)轉(zhuǎn)換為當(dāng)App狀態(tài)不活躍時(shí)能夠被存儲(chǔ)的字符串慧妄;
Currently, only the UITableView and UICollectionView classes support this protocol. You would implement this protocol in any objects you use as the data source for those classes. If you do not adopt the protocol in your data source, the views do not attempt to restore the selected and visible rows.
//目前,只有 UITableView 和 UICollectionView 類(lèi) 支持這個(gè)協(xié)議剪芍。你將可以實(shí)現(xiàn)這個(gè)協(xié)議在任何你用來(lái)作為UITableView 和 UICollectionView數(shù)據(jù)源的對(duì)象中塞淹,如果在你的數(shù)據(jù)源對(duì)象中不實(shí)現(xiàn)這個(gè)協(xié)議,那么視圖將不會(huì)試著去恢復(fù)選中的和可見(jiàn)rows;

我們可以獲取到的主要信息有:

  • 只有 UITableViewUICollectionView類(lèi)支持這個(gè)協(xié)議罪裹。
  • 我們的數(shù)據(jù)源中的每個(gè)數(shù)據(jù)對(duì)象(model)必須具備唯一辨認(rèn)標(biāo)識(shí)饱普。
  • 使用這個(gè)協(xié)議的方法去保證相同的數(shù)據(jù)對(duì)象,(而不僅僅是相同的行的索引)被滾動(dòng)到視圖并且被選中状共。舉個(gè)場(chǎng)景的例子:TableView的數(shù)據(jù)源對(duì)象在上次保存時(shí)套耕,所保存的行的索引,可能會(huì)因?yàn)樵诋?dāng)前運(yùn)行周期內(nèi)數(shù)據(jù)源中數(shù)據(jù)的變動(dòng)發(fā)生變化峡继。從而導(dǎo)致當(dāng)前選中的行所對(duì)應(yīng)的數(shù)據(jù)并非上次保存時(shí)的數(shù)據(jù)冯袍。
  • 若需要使用UIDataSourceModelAssociation,則:實(shí)現(xiàn)了UITableView 和 UICollectionView數(shù)據(jù)源協(xié)議的對(duì)象,負(fù)責(zé)實(shí)現(xiàn)這個(gè)協(xié)議的方法,否則不會(huì)生效康愤。實(shí)際操作發(fā)現(xiàn)確實(shí)如此儡循。

除了官網(wǎng)解釋,在實(shí)際操作中發(fā)現(xiàn)還需要設(shè)置UITableView 或UICollectionView的restorationIdentifier征冷,否則UIDataSourceModelAssociation協(xié)議方法不會(huì)被調(diào)用择膝。關(guān)于UITableView的restorationIdentifier查閱官方文檔如下:

To save and restore the table’s data, assign a nonempty value to the table view’s restorationIdentifier property. When its parent view controller is saved, the table view automatically saves the index paths for the currently selected and visible rows. If the table’s data source object adopts the UIDataSourceModelAssociation protocol, the table stores the unique IDs that you provide for those items instead of their index paths.

UITableView設(shè)置了restorationIdentifier,進(jìn)行UI的保存時(shí)检激,tableView會(huì)自動(dòng)存儲(chǔ)當(dāng)前選中和可見(jiàn)行的索引肴捉。補(bǔ)充:還會(huì)存儲(chǔ)滾動(dòng)偏移,并可以恢復(fù)叔收。

UIDataSourceModelAssociation使用
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    InfoModel *model = [self.dataSource objectAtIndex:indexPath.row];
    
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:NSStringFromClass(UITableViewCell.class) forIndexPath:indexPath];
    cell.textLabel.text = model.title;
    cell.restorationIdentifier = model.identifier;
    
    return cell;
}
- (NSString *)modelIdentifierForElementAtIndexPath:(NSIndexPath *)idx inView:(UIView *)view {
    //根據(jù)index 返回identifier
    NSString *identifier = nil;
    InfoModel *model = [self.dataSource objectAtIndex:idx.row];
    
    /*
     注釋①
     if (idx && view) {
       identifier = model.identifier;
    }
    */
    if (idx.row == _currentPath.row && view) {
        identifier = model.identifier;
    }
    //若是不定義_currentPath追蹤當(dāng)前選中的cell.會(huì)多保存一個(gè)cell齿穗,目前尚未有答案。
    return identifier;
}
//此方法 恢復(fù)時(shí)調(diào)用
- (NSIndexPath *)indexPathForElementWithModelIdentifier:(NSString *)identifier inView:(UIView *)view {
    //根據(jù)identifier 返回index;
    NSIndexPath *indexPath = nil;
    if (identifier && view) {
        __block NSInteger row = 0;
        [self.dataSource enumerateObjectsUsingBlock:^(InfoModel *obj, NSUInteger idx, BOOL * _Nonnull stop) {
            if ([obj.identifier isEqualToString:identifier]) {
                row = idx;
                *stop = YES;
            }
        }];
        indexPath = [NSIndexPath indexPathForRow:row inSection:0];
        _currentPath = indexPath;
        NSLog(@"當(dāng)前選中的數(shù)據(jù)源對(duì)象標(biāo)識(shí)是:%@,對(duì)象抬頭是:%@",[self.dataSource[indexPath.row] identifier],[self.dataSource[indexPath.row] title]);
    }

    return indexPath;
}

上述代碼方法-(NSString *)modelIdentifierForElementAtIndexPath:(NSIndexPath *)idx inView:(UIView *)view中注釋①描述:此方法會(huì)在保存時(shí)調(diào)用兩次今穿,idx所返回的數(shù)據(jù)除了我們選中的行缤灵,還會(huì)返回一個(gè)其他行。 若是采用這種方式映射唯一標(biāo)識(shí)蓝晒,會(huì)出現(xiàn)保存了我們不需要的行的標(biāo)識(shí)腮出,導(dǎo)致恢復(fù)滑動(dòng)位置失效,針對(duì)此問(wèn)題目前筆者尚未有答案芝薇,查閱資料發(fā)現(xiàn)這個(gè)問(wèn)題曾經(jīng)是蘋(píng)果的一個(gè)BUG胚嘲,若是大家知道具體原因,歡迎評(píng)論和補(bǔ)充洛二。目前在此基礎(chǔ)上筆者自己想的解決辦法:定義_currentPath追蹤當(dāng)前選中的cell馋劈,保存時(shí)根據(jù)_currentPath保存我們需要的標(biāo)識(shí),測(cè)試中發(fā)現(xiàn)可以解決問(wèn)題晾嘶。
QIRestorationDemo地址

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末妓雾,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子垒迂,更是在濱河造成了極大的恐慌械姻,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,968評(píng)論 6 482
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件机断,死亡現(xiàn)場(chǎng)離奇詭異楷拳,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)吏奸,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,601評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門(mén)欢揖,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人奋蔚,你說(shuō)我怎么就攤上這事她混。” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 153,220評(píng)論 0 344
  • 文/不壞的土叔 我叫張陵产上,是天一觀的道長(zhǎng)棵磷。 經(jīng)常有香客問(wèn)我,道長(zhǎng)晋涣,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 55,416評(píng)論 1 279
  • 正文 為了忘掉前任沉桌,我火速辦了婚禮谢鹊,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘留凭。我一直安慰自己佃扼,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,425評(píng)論 5 374
  • 文/花漫 我一把揭開(kāi)白布蔼夜。 她就那樣靜靜地躺著兼耀,像睡著了一般。 火紅的嫁衣襯著肌膚如雪求冷。 梳的紋絲不亂的頭發(fā)上瘤运,一...
    開(kāi)封第一講書(shū)人閱讀 49,144評(píng)論 1 285
  • 那天,我揣著相機(jī)與錄音匠题,去河邊找鬼拯坟。 笑死,一個(gè)胖子當(dāng)著我的面吹牛韭山,可吹牛的內(nèi)容都是我干的郁季。 我是一名探鬼主播,決...
    沈念sama閱讀 38,432評(píng)論 3 401
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼钱磅,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼梦裂!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起盖淡,我...
    開(kāi)封第一講書(shū)人閱讀 37,088評(píng)論 0 261
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤年柠,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后禁舷,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體彪杉,經(jīng)...
    沈念sama閱讀 43,586評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,028評(píng)論 2 325
  • 正文 我和宋清朗相戀三年牵咙,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了派近。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,137評(píng)論 1 334
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡洁桌,死狀恐怖渴丸,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤谱轨,帶...
    沈念sama閱讀 33,783評(píng)論 4 324
  • 正文 年R本政府宣布戒幔,位于F島的核電站,受9級(jí)特大地震影響土童,放射性物質(zhì)發(fā)生泄漏诗茎。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,343評(píng)論 3 307
  • 文/蒙蒙 一献汗、第九天 我趴在偏房一處隱蔽的房頂上張望敢订。 院中可真熱鬧,春花似錦罢吃、人聲如沸楚午。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,333評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)矾柜。三九已至,卻和暖如春就谜,著一層夾襖步出監(jiān)牢的瞬間怪蔑,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,559評(píng)論 1 262
  • 我被黑心中介騙來(lái)泰國(guó)打工吁伺, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留饮睬,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 45,595評(píng)論 2 355
  • 正文 我出身青樓篮奄,卻偏偏與公主長(zhǎng)得像捆愁,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子窟却,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,901評(píng)論 2 345

推薦閱讀更多精彩內(nèi)容