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