【问题标题】:How does iOS 6 UIWebView state restoration work?iOS 6 UIWebView 状态恢复如何工作?
【发布时间】:2013-01-13 07:45:21
【问题描述】:

根据docs

在 iOS 6 及更高版本中,如果您为此视图的 restoreIdentifier 属性分配一个值,它会尝试保留其 URL 历史记录、每个页面的缩放和滚动位置以及有关当前正在查看哪个页面的信息。在恢复过程中,视图会恢复这些值,以便网页内容与之前一样。

我正在做所有这些,但什么都没有发生。即使我手动保存和恢复用户之前查看的 URL,滚动位置也不会恢复。文档有误吗?

【问题讨论】:

    标签: ios6 uiwebview restore state-restoration


    【解决方案1】:

    文档是正确的,但非常不完整。这是正在发生的事情。如果 Web 视图参与状态恢复(我假设您知道这意味着什么 - 一切都必须有一个 restorationIdentifier,等等),并且如果 Web 视图在用户有请求(不是 HTML 字符串)时离开应用程序后,Web 视图将自动恢复,包含与其request 属性相同的请求,并且其后退和前进列表完好无损。因此,您可以使用状态恢复机制来恢复 Web 视图的状态,但您必须执行一些额外的操作。这种舞蹈是如此的好奇和晦涩,以至于最初我的印象是 Web 视图的状态无法真正保存和恢复,尽管文档声称它可以。

    这里有两个秘密;一旦你了解了它们,你就会明白网络视图状态恢复:

    • 已恢复的 Web 视图不会自动加载其请求;这取决于您的代码。

    • 在恢复的 Web 视图加载其请求后,其后退列表中的第一项是与用户离开它的状态相同的页面(滚动和缩放)。

    了解这一点后,您就可以轻松设计出一种用于恢复 Web 视图状态的策略。第一件事是检测我们正在恢复状态,并提出一个这样的标志:

    -(void)decodeRestorableStateWithCoder:(NSCoder *)coder {
        [super decodeRestorableStateWithCoder:coder];
        self->_didDecode = YES;
    }
    

    现在我们可以检测(也许在viewDidAppear:)我们正在恢复状态,并且网络视图神奇地包含一个请求,并加载该请求:

    if (self->_didDecode && wv.request)
        [wv loadRequest:wv.request];
    

    现在是棘手的部分。视图加载后,我们立即“返回”。这实际上具有恢复用户先前滚动位置的效果(以及从 Back 堆栈顶部删除额外条目)。然后我们降下我们的旗帜,这样我们就不会在其他任何时候采取这种额外的行动:

    - (void)webViewDidFinishLoad:(UIWebView *)wv {
        if (self->_didDecode && wv.canGoBack)
            [wv goBack];
        self->_didDecode = NO;
    }
    

    UIWebView 现在处于用户之前离开应用时的状态。我们已经使用内置的 iOS 6 状态保存和恢复功能保存和恢复了状态。

    【讨论】:

    • 我不知道这是否是网络浏览量的怪癖,但在[wv goBack] 之后,测试[wv canGoBack] 仍然返回YES,一次又一次。在历史记录中只有一页的网络视图上尝试过(iOS 6.1.4)。
    • 在任何地方都有这样的项目吗?无法让它工作
    • 出于好奇,一个人如何在一个复杂、令人费解的问题上提出一个伟大的问题,然后用一个全面的自我答案迅速消除它,非常详细,所有这些都在 2 的范围内分钟?好的!这个技巧的 SO 徽章在哪里?
    • @GregCombs stackoverflow.com/help/self-answer "如果您有一个您已经知道答案的问题,并且您想公开记录该知识以便其他人(包括您自己)以后可以找到它,那就是完全可以在 Stack Exchange 网站上提出和回答您自己的问题。” - 当然,您缺少的是在发布问答之前在此问题上的几周工作。
    • 大声笑,明白了!我当然很高兴你这样做了!
    【解决方案2】:

    我已经尝试了 Matt 的回答并且效果很好,但是如果历史堆栈中有“转发”页面,它们将被 Web 视图对象中恢复的请求替换。

    更好的方法是在 webview 对象上调用 'reload' 方法,这将恢复两个方向的历史记录以及缩放和内容滚动偏移量。

    如果您想要我的方法示例或您自己的 web 视图的更多功能,请查看我的 SVWebViewController here. 的开源分支

    【讨论】:

    • 这比我的回答好!
    • 每个人都应该阅读马特的回答,以了解发生了什么以及代码显示在哪里。只需将他的“loadRequest”调用替换为“reload”即可。
    猜你喜欢
    • 2012-09-16
    • 1970-01-01
    • 1970-01-01
    • 2015-11-21
    • 2013-10-25
    • 2012-09-10
    • 1970-01-01
    • 1970-01-01
    • 2012-05-23
    相关资源
    最近更新 更多