16

我有一个基于 webView 的应用程序,但我希望用户能够通过在触控板和魔术鼠标上滑动来导航它。因此,我要实现 NSPageController。

我查看了文档和 PictureSwiper 应用程序,但是这些并不是真正用于 webView。所以,我想知道如何在 webView 上使用 NSPageController。我有一个 webView 定义为webView和两个动作,goBack: 和 goForward: 分别加载上一页和下一页。

但是,我不知道如何让 NSPageController 与简单的 webView 一起工作。有一种方法可以做到这一点,但我认为没有办法。如果有人可以请解释我应该做什么,那就太好了。或者,如果您感觉特别大方,可以下载我的免费浏览器源示例。https://sites.google.com/site/infiniteopensyntax/basic-web-browser

该来源显示了我自己的应用程序是如何设置的。如果您想在该应用程序上实现 NSPageController 并将源代码发送给我,我将不胜感激。这并不多,但如果你这样做,我会将滑动示例添加到 Infinite Open Syntax 并在上面写上你的名字。您可以选择许可证。

这是 Cocoa,不是 Cocoa Touch

编辑

好的,现在我只需要确保该应用程序仍然可以在 Snow Leopard 上运行。据说,我可以通过断开插座来测试它。它工作正常,减去后退和前进按钮。为此,我相信我检查了 NSPageController 类。如果它不存在,那么我只是跳过使用 pageController。

- (IBAction)goBack:(id)sender {
    if (NSClassFromString(@"NSPageController") != Nil)
    {
        [self.pageController navigateBack:sender];
    }
    {

         //Not 10.8
        [webView goBack];
    }
}
4

2 回答 2

9

您链接到的页面上的下载链接不起作用,所以我会保持我的回答更笼统。

如果您正在使用,则无需保留多个 WebView 或手动生成快照NSPageController;它会为您解决这个问题。在您的情况下,您想NSPageControllerHistory 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 作为对象。您可能需要采取不同的做法。

如果您需要更多帮助,请告诉我。

于 2012-12-19T06:49:20.563 回答
1

来自: https ://stackoverflow.com/a/13716988/466698

一个明显的解决方案可能是使用多个 Web 视图,但由于它们可能非常重,您可能不想这样做。

最好的想法可能是在离开之前保存每个页面的图像。当用户向后滑动时,只显示保存图像的视图。滑动完成后,交换视图以使 Web 视图本身位于顶部。

这似乎是 Safari 的做法(您有时可以看到图像压缩,并且它经常重新加载页面并跳离上一个屏幕截图)

于 2012-12-15T07:39:10.803 回答