您链接到的页面上的下载链接不起作用,所以我会保持我的回答更笼统。
如果您正在使用,则无需保留多个 WebView 或手动生成快照NSPageController
;它会为您解决这个问题。在您的情况下,您想NSPageController
在History Mode中使用。为此,请将您WebView
连接到pageController.view
. 您将需要实现三种NSPageControllerDelegate
方法:
- (void)pageControllerWillStartLiveTransition:(NSPageController *)pageController;
- (void)pageController:(NSPageController *)pageController didTransitionToObject:(id)object;
- (void)pageControllerDidEndLiveTransition:(NSPageController *)pageController;
每次 WebView 进入新页面(不是通过后退/前进操作)时,调用navigateForwardToObject:(id)object
. pageController
我会创建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:
将被调用。凉爽的。在该方法中您应该做的是抓住WebHistoryItem
并让 WebView 使用该方法object
返回该项目。goToBackForwardItem:
您还应该保留您存储的用户状态object
(例如,在实例变量中),因为您需要在WebView
完成加载后恢复它。
最后,在pageControllerDidEndLiveTransition:
重新显示 WebView 之前,您可以做任何您想做的事情。我希望这没什么,因为在 WebView 完成加载之前不会恢复用户状态,所以您在其实现中需要的只是[pageController completeTransition]
.
最后一个细节是后退/前进按钮。您应该像往常一样实现它们,但也让它们调用navigateBack:
或navigateForward:
在 pageController 上。
这几乎涵盖了它。我实际上没有尝试过这个具体的例子,所以如果你遇到任何问题,请告诉我。
编辑
以下是我如何修改您的源以获得基本NSPageController
功能。NSPageController IBOutlet
在 AppDelegate 头文件中添加一个属性。在您的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]
。
请注意,我没有费心在此处保存任何用户状态,而是WebHistoryItem
直接使用 s 作为对象。您可能需要采取不同的做法。
如果您需要更多帮助,请告诉我。