您链接到的页面上的下载链接不起作用,所以我会保持我的回答更笼统。
如果您使用NSPageController,则无需保留多个 WebView 或手动生成快照;它会为您解决这个问题。在您的情况下,您想在History Mode 中使用NSPageController。为此,请将您的WebView 连接到pageController.view。您将需要实现三个NSPageControllerDelegate 方法:
- (void)pageControllerWillStartLiveTransition:(NSPageController *)pageController;
- (void)pageController:(NSPageController *)pageController didTransitionToObject:(id)object;
- (void)pageControllerDidEndLiveTransition:(NSPageController *)pageController;
每次 WebView 进入新页面(不是通过后退/前进操作)时,请在 pageController 上调用 navigateForwardToObject:(id)object。我会让object 成为一个自定义对象,用于存储导航页面的用户状态(滚动位置、突出显示的文本、表单内容等)以及页面的WebHistoryItem。用户状态最初可以是未定义的,但应该在pageControllerWillStartLiveTransition: 中设置。这是一个例子:
- (void)pageControllerWillStartLiveTransition:(NSPageController *)pageController
{
// Remember user state
MyCustomObject *object = [self.pageController.arrangedObjects objectAtIndex:self.pageController.selectedIndex];
object.userState = someUserState;
}
当该方法返回时,pageController 将隐藏其视图(WebView)并显示其视图先前状态的快照。
滑动动画完成后,pageController:didTransitionToObject: 将被调用。凉爽的。在该方法中您应该做的是从object 中获取WebHistoryItem,并使用goToBackForwardItem: 方法让WebView 返回该项目。您还应该保留您存储在 object 中的用户状态(例如,在实例变量中),因为您需要在 WebView 完成加载后恢复它。
最后,在pageControllerDidEndLiveTransition: 中,您可以在重新显示 WebView 之前做任何您想做的事情。我希望这没什么,因为在 WebView 完成加载之前不会恢复用户状态,因此您在其实现中需要的只是[pageController completeTransition]。
最后一个细节是后退/前进按钮。您应该像往常一样实现它们,但也让它们在 pageController 上调用 navigateBack: 或 navigateForward:。
这几乎涵盖了它。我实际上没有尝试过这个具体的例子,所以如果你遇到任何问题,请告诉我。
编辑
以下是我将如何修改您的源以获得基本的NSPageController 功能。在 AppDelegate 头文件中添加 NSPageController IBOutlet 属性。在您的MainMenu.xib 文件中添加页面控制器,将其视图连接到您的WebView,将您的AppDelegate 设置为它的委托,并为其提供我们刚刚在AppDelegate 中创建的属性的引用出口。另外,让您的 AppDelegate 成为您的 WebView 的frameLoadDelegate。在basicWebAppDelegate.m里面添加一个私有属性:
@interface basicWebAppDelegate ()
@property (assign) id currentItem;
@end
然后在里面添加如下实现:
#pragma mark - WebFrameLoadDelegate
- (void)webView:(WebView *)sender didCommitLoadForFrame:(WebFrame *)frame {
if (frame == [sender mainFrame]) {
id object = [sender.backForwardList currentItem];
BOOL isCurrentItem = self.currentItem && (object == self.currentItem) ? YES : NO;
if (!isCurrentItem) {
[self.pageController navigateForwardToObject:[sender.backForwardList currentItem]];
}
}
}
#pragma mark - NSPageControllerDelegate
- (void)pageControllerWillStartLiveTransition:(NSPageController *)pageController {
self.currentItem = [self.webView.backForwardList currentItem];
// Here is where you'll save any state for your pageController.arrangedObjects[pageController.selectedIndex] object
}
- (void)pageController:(NSPageController *)pageController didTransitionToObject:(id)object {
BOOL isCurrentItem = self.currentItem && (object == self.currentItem) ? YES : NO;
if (!isCurrentItem) {
self.currentItem = object;
[self.webView goToBackForwardItem:object];
}
}
- (void)pageControllerDidEndLiveTransition:(NSPageController *)pageController {
self.currentItem = nil;
[pageController completeTransition];
}
最后,将您的 goBack: 和 goForward: 操作更改为分别调用 [self.pageController navigateBack:sender] 和 [self.pageController navigateForward:sender]。
请注意,我没有费心在此处保存任何用户状态,而是直接使用WebHistoryItems 作为对象。您可能需要采取不同的做法。
如果您需要更多帮助,请告诉我。