你如何实现 NSPageController 来浏览 webView 的历史记录 [英] How do you implement NSPageController to navigate through a webView's history

查看:15
本文介绍了你如何实现 NSPageController 来浏览 webView 的历史记录的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

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

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

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

这是 Cocoa,不是 Cocoa Touch

编辑

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

- (IBAction)goBack:(id)sender {if (NSClassFromString(@"NSPageController") != Nil){[self.pageController navigateBack:sender];}{//不是10.8[webView 返回];}}

解决方案

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

如果您使用 NSPageController,则不需要保留多个 WebView 或手动生成快照;它会为您解决这个问题.在您的情况下,您希望在 历史模式.为此,请将您的 WebView 连接到 pageController.view.您需要实现三个 NSPageControllerDelegate 方法:

- (void)pageControllerWillStartLiveTransition:(NSPageController *)pageController;- (void)pageController:(NSPageController *)pageController didTransitionToObject:(id)object;- (void)pageControllerDidEndLiveTransition:(NSPageController *)pageController;

每次 WebView 转到新页面时(不是通过后退/前进操作),调用 navigateForwardToObject:(id)objectpageController.我将使 object 成为一个自定义对象,用于存储导航页面的用户状态(滚动位置、突出显示的文本、表单内容等)以及页面的 WebHistoryItem.用户状态最初可以是未定义的,但应该在 pageControllerWillStartLiveTransition: 中设置.举个例子:

- (void)pageControllerWillStartLiveTransition:(NSPageController *)pageController{//记住用户状态MyCustomObject *object = [self.pageController.arrangedObjects objectAtIndex:self.pageController.selectedIndex];object.userState = someUserState;}

当该方法返回时,pageController 将隐藏其视图(WebView)并显示其视图先前状态的快照.

一旦滑动动画完成,pageController:didTransitionToObject: 将被调用.凉爽的.在该方法中您应该做的是从 object 中获取 WebHistoryItem 并让 WebView 使用 goToBackForwardItem: 方法.您还应该保留您存储在 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;@结尾

然后在内部实现中添加以下内容:

#pragma mark - WebFrameLoadDelegate- (void)webView:(WebView *)sender didCommitLoadForFrame:(WebFrame *)frame {if (frame == [sender mainFrame]) {id object = [sender.backForwardList currentItem];BOOL isCurrentItem = self.currentItem &&(对象== self.currentItem)?是:否;如果(!isCurrentItem){[self.pageController navigateForwardToObject:[sender.backForwardList currentItem]];}}}#pragma mark - NSPageControllerDelegate- (void)pageControllerWillStartLiveTransition:(NSPageController *)pageController {self.currentItem = [self.webView.backForwardList currentItem];//这里是你为 pageController.arrangedObjects[pageController.selectedIndex] 对象保存任何状态的地方}- (void)pageController:(NSPageController *)pageController didTransitionToObject:(id)object {BOOL isCurrentItem = self.currentItem &&(对象== self.currentItem)?是:否;如果(!isCurrentItem){self.currentItem = 对象;[self.webView goToBackForwardItem:object];}}- (void)pageControllerDidEndLiveTransition:(NSPageController *)pageController {self.currentItem = nil;[pageController completeTransition];}

最后,将您的 goBack:goForward: 操作更改为仅调用 [self.pageController navigateBack:sender][self.pageController navigateForward:sender],分别.

请注意,我没有费心在这里保存任何用户状态,而是直接使用 WebHistoryItem 作为对象.您可能需要采取不同的做法.

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

I have a webView-based app, but I want the user to be able to navigate it with swiping on the trackpad and magic mouse. Therefore, I am going to implement NSPageController.

I have looked at the documentation and the PictureSwiper app, however those aren't really meant for a webView. So, I would like to know how I can use an NSPageController on a webView. I have a webView defined as webView and two actions, goBack: and goForward: that load the previous and next page respectively.

However, I am unaware of how I get NSPageController to work with a simple webView. There has a to be a way to do it, but I see no way. If someone could please explain what I am suppose to do, that would be great. Or if you are feeling especially generous, you can download my free browser source example. https://sites.google.com/site/infiniteopensyntax/basic-web-browser

That source shows how my own app is pretty much set up. If you would like to implement the NSPageController on that app and send me the source, I would really appreciate it. It's not much, but if you do that I'll add the swiping example to Infinite Open Syntax and put your name on it. You can choose the license.

This is Cocoa, not Cocoa Touch

EDIT

Okay, now I just need to make sure the app still works on Snow Leopard. Supposedly, I can test this by disconnecting the outlets. It works fine, minus the back and forward button. To do this, I believe I check for the class NSPageController. If it doesn't exist, then I just skip using the pageController.

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

         //Not 10.8
        [webView goBack];
    }
}

解决方案

The download link on the page you linked to doesn't work, so I'll keep my answer more general.

You don't need to keep multiple WebViews or manually generate snapshots if you're using NSPageController; it takes care of that for you. In your case, you want to use NSPageController in History Mode. To do that, wire your WebView to pageController.view. You will need to implement three NSPageControllerDelegate methods:

- (void)pageControllerWillStartLiveTransition:(NSPageController *)pageController;
- (void)pageController:(NSPageController *)pageController didTransitionToObject:(id)object;
- (void)pageControllerDidEndLiveTransition:(NSPageController *)pageController;

Every time the WebView goes to a new page (not through a back/forward action), call navigateForwardToObject:(id)object on the pageController. I would make object a custom object that stores user state for a navigated page (scroll positions, highlighted text, form contents, etc.) as well as the page's WebHistoryItem. The user state can be undefined initially, but should get set in pageControllerWillStartLiveTransition:. Here's an example:

- (void)pageControllerWillStartLiveTransition:(NSPageController *)pageController
{
  // Remember user state
  MyCustomObject *object = [self.pageController.arrangedObjects objectAtIndex:self.pageController.selectedIndex];
  object.userState = someUserState;
}

When that method returns, the pageController will hide its view (the WebView) and display snapshots of previous states of its view instead.

Once the swiping animation is complete, pageController:didTransitionToObject: will get called. Cool. What you should do in that method is grab the WebHistoryItem out of object and have the WebView go back to that item using the goToBackForwardItem: method. You should also hold onto the user state you stored in object (say, in an instance variable), because you'll need to restore it once WebView finishes loading.

Lastly, in pageControllerDidEndLiveTransition: you do anything you want done before redisplaying the WebView. I expect that would be nothing, since the user state isn't restored until the WebView finishes loading, so all you would need in its implementation would be [pageController completeTransition].

One last detail is the back/forward buttons. You should implement them as you would normally, but also have them call navigateBack: or navigateForward: on the pageController.

That pretty much covers it. I haven't actually tried this specific example, so let me know if you run into any problems.

Edit

Here's how I'd modify your source to get basic NSPageController functionality. Add an NSPageController IBOutlet property in your AppDelegate header file. In your MainMenu.xib file add the page controller, wire its view to your WebView, make your AppDelegate its delegate, and give it a referencing outlet to the property we just created in the AppDelegate. Also, make your AppDelegate your WebView's frameLoadDelegate. Inside basicWebAppDelegate.m add a private property:

@interface basicWebAppDelegate ()
@property (assign) id currentItem;
@end

Then add the following inside implementation:

#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];
}

Finally, change your goBack: and goForward: actions to just call [self.pageController navigateBack:sender] and [self.pageController navigateForward:sender], respectively.

Note that I didn't bother saving any user state here and instead used WebHistoryItems directly as the objects. You might need to do differently.

Let me know if you need more help.

这篇关于你如何实现 NSPageController 来浏览 webView 的历史记录的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆