Как реализовать NSPageController для навигации по истории веб-просмотра

У меня есть приложение, основанное на веб-браузере, но я хочу, чтобы пользователь мог перемещаться по нему с помощью трекинга и волшебной мыши. Поэтому я собираюсь реализовать NSPageController.

Я просмотрел документацию и приложение PictureSwiper, однако они не предназначены для webView. Итак, я хотел бы знать, как я могу использовать NSPageController в webView. У меня есть webView, определяемый как webView и два действия: goBack: и goForward: загружают предыдущую и следующую страницу соответственно.

Однако я не знаю, как я могу заставить NSPageController работать с простым webView. Должен быть способ сделать это, но я не вижу никакого способа. Если кто-то может объяснить, что я должен делать, это было бы здорово. Или, если вы чувствуете себя особенно щедрым, вы можете загрузить мой бесплатный пример источника браузера. https://sites.google.com/site/infiniteopensyntax/basic-web-browser

Этот источник показывает, как мое собственное приложение в значительной степени настроено. Если вы хотите реализовать NSPageController в этом приложении и отправить мне источник, я бы очень признателен. Это не так много, но если вы это сделаете, я добавлю пример swiping в Infinite Open Syntax и поместил бы ваше имя на него. Вы можете выбрать лицензию.

Это Cocoa, а не Cocoa Нажмите

ИЗМЕНИТЬ

Хорошо, теперь мне просто нужно убедиться, что приложение все еще работает на Snow Leopard. Предположительно, я могу проверить это, отключив розетки. Он отлично работает, минус кнопка "назад" и "вперед". Для этого я считаю, что проверяю класс NSPageController. Если он не существует, я просто пропущу с помощью pageController.

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

         //Not 10.8
        [webView goBack];
    }
}

Ответы

Ответ 1

Ссылка для загрузки на странице, с которой вы связаны, не работает, поэтому я сохраню свой ответ более общим.

Вам не нужно сохранять несколько WebView или вручную создавать моментальные снимки, если вы используете NSPageController; это позаботится об этом для вас. В вашем случае вы хотите использовать NSPageController в режиме истории. Для этого подключите 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. Сначала пользовательское состояние может быть undefined, но должно быть установлено в 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 из object и вернуть WebView к этому элементу с помощью goToBackForwardItem: метод. Вы также должны придерживаться состояния пользователя, которое вы сохранили в object (например, в переменной экземпляра), потому что вам нужно будет восстановить его один раз WebView завершает загрузку.

Наконец, в pageControllerDidEndLiveTransition: вы делаете все, что хотите, перед повторным отображением WebView. Я ожидаю, что это будет ничто, поскольку пользовательское состояние не будет восстановлено до тех пор, пока WebView не завершит загрузку, поэтому все, что вам понадобится в его реализации, будет [pageController completeTransition].

Одна из последних деталей - кнопки назад/вперед. Вы должны реализовывать их так, как обычно, но также им нужно позвонить navigateBack: или navigateForward: на страницеController.

Это в значительной степени покрывает его. Я действительно не пробовал этот конкретный пример, поэтому дайте мне знать, если у вас возникнут проблемы.

Изменить

Вот как я могу изменить ваш источник, чтобы получить базовую функциональность 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 непосредственно как объекты. Возможно, вам придется поступить иначе.

Сообщите мне, если вам нужна дополнительная помощь.

Ответ 2

С: fooobar.com/info/327006/...

Очевидным решением может быть использование нескольких веб-представлений, но поскольку они могут быть довольно тяжелыми, вы, вероятно, не хотите.

Лучшая идея - это, вероятно, сохранить изображение каждой страницы перед тем, как перейти от нее. Когда использование отскакивает назад, покажите представление только с сохраненным изображением. После того, как салфетка будет завершена, поменяйте местами вокруг, так что веб-представление будет сверху.

Это похоже на то, как это делает Safari (иногда вы можете увидеть сжатие изображения, и он часто перезагружает страницу, и она отскакивает от предыдущего скриншота)