簡體   English   中英

UIKit狀態保存不恢復滾動偏移

[英]UIKit state preservation not restoring scroll offset

我有一個在iOS 6中使用UIKit狀態保存的應用程序。我能夠保存/恢復視圖控制器的狀態,即選擇了哪個選項卡和導航控制器層次結構,但是我無法獲取我的表視圖來恢復它的偏移量。 我的故事板中有一個恢復標識符用於視圖以及視圖控制器和視圖控制器(表的數據源)實現UIDataSourceModelAssociation ,如下所示:

- (NSString *)modelIdentifierForElementAtIndexPath:(NSIndexPath *)indexPath inView:(UIView *)view
{
    TSStatus *status = [self._fetchedResultsController objectAtIndexPath:indexPath];

    return status.objectID.URIRepresentation.absoluteString;
}

- (NSIndexPath *)indexPathForElementWithModelIdentifier:(NSString *)identifier inView:(UIView *)view
{
    NSURL *statusURL = [NSURL URLWithString:identifier];
    NSManagedObjectID *statusID = [[TSDataController sharedController].persistentStoreCoordinator managedObjectIDForURIRepresentation:statusURL];
    TSStatus *status = (TSStatus *)[[TSDataController sharedController].mainContext objectWithID:statusID];

    return [__fetchedResultsController indexPathForObject:status];
}

modelIdentifierForElementAtIndexPath:inView:在應用程序進入后台時被調用,但是modelIdentifierForElementAtIndexPath:inView:永遠不會被調用。

這不是你問題的真正答案,但我也無法讓表格視圖恢復其contentOffset。

我想這是iOS 6中的一個錯誤,因為文檔明確指出UITableView恢復其contentOffset,1)它有一個restorationIdentifier 2)視圖所屬的視圖控制器有一個restorationIdentifier和3)數據源符合UIDataSourceModelAssociation協議。

您可以在視圖控制器中手動恢復contentOffset和所選項目,但是:

- (void)encodeRestorableStateWithCoder:(NSCoder *)coder
{
    [super encodeRestorableStateWithCoder:coder];

    [coder encodeObject:[NSValue valueWithCGPoint:self.tableView.contentOffset] forKey:@"tableView.contentOffset"];

    NSIndexPath *indexPath = [self.tableView indexPathForSelectedRow];
    if (indexPath != nil) {
        NSString *modelIdentifier = [self modelIdentifierForElementAtIndexPath:indexPath inView:self.tableView];
        [coder encodeObject:modelIdentifier forKey:@"tableView.selectedModelIdentifier"];
    }
}

- (void)decodeRestorableStateWithCoder:(NSCoder *)coder
{
    [super decodeRestorableStateWithCoder:coder];

    CGPoint contentOffset = [[coder decodeObjectForKey:@"tableView.contentOffset"] CGPointValue];
    self.tableView.contentOffset = contentOffset;

    NSString *modelIdentifier = [coder decodeObjectForKey:@"tableView.selectedModelIdentifier"];
    if (modelIdentifier != nil) {
        NSIndexPath *indexPath = [self indexPathForElementWithModelIdentifier:modelIdentifier inView:self.tableView];
        if (indexPath != nil) {
            [self.tableView selectRowAtIndexPath:indexPath animated:NO scrollPosition:UITableViewScrollPositionNone];
        }
    }
}

我不知道為什么UITableView不會自動執行此操作,即使文檔說它確實如此。 如果有人知道答案,請發表評論。

我發現這可以工作,如果UITableView 有一個restorationIdentifier設置。

但是,如果UITableViewController在UINavigationController中,它就不起作用。 這已經報告給Apple,問題ID:13536778。iOS 6.0和6.1.3上似乎都出現了這個問題。

這是iOS 6中的一個錯誤。

要使用UIDataSourceModelAssociation協議獲取表視圖的狀態恢復,您應該在表視圖上調用-reloadData ,然后在-indexPathForElementWithModelIdentifier:inView:返回有效的索引路徑-indexPathForElementWithModelIdentifier:inView:如下所示:

- (NSIndexPath *)indexPathForElementWithModelIdentifier:(NSString *)identifier inView:(UIView *)view
{
    NSURL *statusURL = [NSURL URLWithString:identifier];
    NSManagedObjectID *statusID = [[TSDataController sharedController].persistentStoreCoordinator managedObjectIDForURIRepresentation:statusURL];
    TSStatus *status = (TSStatus *)[[TSDataController sharedController].mainContext objectWithID:statusID];

    [self.tableView reloadData];

    return [__fetchedResultsController indexPathForObject:status];
}

有關如何實現此目的,請參閱Apple的State恢復示例。 魔術修復發生在decodeRestorableStateWithCoder方法中,並調用reloadData

MyTableViewController.m

// this is called when the app is re-launched
- (void)decodeRestorableStateWithCoder:(NSCoder *)coder
{
    // important: don't affect our views just yet, we might not visible or we aren't the current
    // view controller, save off our ivars and restore our text view in viewWillAppear
    //
    NSLog(@"MyTableViewController: decodeRestorableStateWithCoder");

    [super decodeRestorableStateWithCoder:coder];

    self.tableView.editing = [coder decodeBoolForKey:kUnsavedEditStateKey];

    [self.tableView reloadData];
}

請注意,編輯狀態很奇怪,因為編輯在保存開始之前由其輸入后台通知處理程序結束,因此它將始終恢復不編輯。 他們也嘗試設置self.tableView.editing而不是self.editing,因此編輯按鈕不會更新。 還要注意關於不影響視圖的注釋,這些注釋首先是奇怪的,因為它們會影響視圖,第二個viewWillAppear在解碼狀態之前被調用。 鑒於這些錯誤,我不會用這個例子來調整你的編程技巧。

另一個答案指出要在indexPathForElementWithModelIdentifier中重新加載,這不是一個好主意,因為它被多次調用(至少兩次)以查找可見和所選對象的各種索引路徑。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM