2012-11-06 15 views
7

我目前正在iOS6專用應用程序中實現自動狀態保存/恢復。對modelIdentifierForElementAtIndexPath的奇怪調用:inView:(UIDataSourceModelAssociation)

對於表視圖的恢復,我添加UIDataSourceModelAssociation協議到我的表視圖控制器和實施

- (NSString *)modelIdentifierForElementAtIndexPath:(NSIndexPath *)idx inView:(UIView *)view

- (NSIndexPath *)indexPathForElementWithModelIdentifier:(NSString *)identifier inView:(UIView *)view

當按下家庭按鈕時,狀態保存方法(包括modelIdentifierForElementAtIndexPath:iView:)正按預期方式調用,並返回給定索引路徑的有效標識符字符串。

當殺死應用程序並重新啓動它時,狀態恢復或多或少地起作用。即該應用程序重新打開正確的表格視圖。但是,表格視圖始終滾動到頂部,即使滾動到另一個位置之前。

下面是我的表視圖控制器中的UIDataSourceModelAssociation方法的實現。沒有什麼幻想,在那裏往前走(的NdlFriend::accountUid屬性返回給定NdlFriend記錄的唯一標識符字符串):

#pragma mark - UIDataSourceModelAssociation 
- (NSString *)modelIdentifierForElementAtIndexPath:(NSIndexPath *)idx inView:(UIView *)view 
{ 
    NSString* identifier = nil; 
    NSArray* content = self.contentArray; 

    // Sometimes idx might be nil... 
    if(idx && idx.row<content.count) 
    { 
     NdlFriend* friend = content[idx.row]; 
     identifier=friend.accountUid; 
    } 
    return identifier; 
} 

- (NSIndexPath *)indexPathForElementWithModelIdentifier:(NSString *)identifier inView:(UIView *)view 
{ 
    NSIndexPath * indexPath=nil; 
    NSArray* content = self.contentArray; 
    NSInteger count = content.count; 
    for(NSInteger i=0;i<count;i++) 
    { 
     NdlFriend* friend = content[i]; 
     if([identifier isEqualToString:friend.accountUid]) 
     { 
      indexPath = [NSIndexPath indexPathForRow:i inSection:0]; 
      break; 
     } 
    } 
    return indexPath; 
} 

我設置這兩種方法突破點。

爲了測試方法,我打開了表格視圖並向下滾動了一下。然後,當按下主頁按鈕時:

  • modelIdentifierForElementAtIndexPath:inView:被調用一次,最上面可見行的索引路徑。該方法爲該行返回正確的uid。

到目前爲止好。

然後我停下來重新啓動應用程序。這裏是發生了什麼(我特別是第一次打破發點疑惑):

  • modelIdentifierForElementAtIndexPath:inView:被調用,以nil作爲索引路徑(視圖參數包含表視圖的正確的指針)。
  • indexPathForElementWithModelIdentifier:inView:被一個有效的標識符字符串調用(並且該方法返回一個有效的索引路徑)。
  • indexPathForElementWithModelIdentifier:inView:被再次調用(使用相同的標識符字符串)。
  • 表格視圖刷新,但滾動到最頂端。

有人知道,爲什麼滾動位置的恢復失敗? modelIdentifierForElementAtIndexPath:inView:nil作爲indexPath可能與它有什麼關係(或者這是正常行爲)。

+1

儘管表格視圖滾動位置(大部分)的恢復現在在iOS 9中起作用,但在空表視圖有時會出現'modelIdentifierForElementAtIndexPath:inView:'_gets調用的問題恢復,導致_bad訪問異常。解決方法是將方法簽名更改爲接受可壓縮的'NSIndexPath!',並防止'nil'(通過返回'nil'),即使它不應該發生**! (或者,爲了避免警告,如果'numberOfRowsInSection(0)'爲零,則返回'nil'也是可行的。) – penfold

回答

0

我不認爲你有關於表視圖的滾動位置重置的問題與UIDataSourceModelAssociation方法有關。

我相信有一個嵌入導航控制器的表格視圖控制器的錯誤,導致它恢復後重置其滾動位置。據我所知,如果你的表視圖中的單元格不重新排序,你不需要實現UIDataSourceModelAssociation方法,你應該獲得「免費」的滾動位置(即只要你選擇了保存狀態並設置恢復ID)。我不能從文檔中明確地確認這一點,除非指出UITableView是從UIScrollView繼承而來的,它保存了它的滾動位置。我已經測試過,如果您將表視圖控制器設置爲根控制器,或者將表視圖控制器嵌入到選項卡欄控制器中,則滾動位置被還原爲

我已經提交了一個錯誤報告,如果您還沒有提交錯誤報告,您也應該這樣做。

1

有一個在iOS 6中關於導航控制器表視圖的狀態恢復的錯誤。

你可以看到開雷達的位置:rdar://13438788

正如你可以看到,這是一個重複的,所以蘋果都意識到了這一點。另外,看到這個下一個鏈接,發佈該公開雷達的人也做了這篇博客文章,它有蘋果工程師告訴他的建議變通辦法。

它使得我的狀態保存/恢復不是一個令人愉快的功能來實現,但請記住,這是爲您的用戶!所以你應該只是做解決方法。

注有2種解決方法,一個是表視圖的視圖信息來恢復(滾動例如偏移),另一個解決辦法實現UIDataSourceModelAssociation時,這是你的情況下使用。

http://useyourloaf.com/blog/2013/04/07/bug-table-view-state-not-restored-when-embedded-in-navigation-controller.html

0

確保你沒有執行異步的數據提取。如果您從viewDidLoad獲取數據,請確保使用[myManagedObjectContext performBlockAndWait:^ {}]調用,而不是[myManagedObjectContext performBlock:^ {}]。

這可能是因爲當你調用indexPathForElementWithModelIdentifier時,你有一個競爭條件,其中self.contentArray爲空。