background
Usually when WKWebView opens a page and receives page data, the proxy method senses when:
-webView:didCommitNavigation:
Copy the code
However, if the page hash (that is, the location identifier “#”) is changed to open another page, this proxy method is not called, and there is no appropriate callback interface.
In performance, change the hash can produce web history stack, safari also produces the history, the scene should be and – webView: didCommitNavigation: corresponding to the callback, the official didn’t complete consistency, through its source further explore cognitive way.
Source code analysis
Breakpoint view trigger – webView: didCommitNavigation: the call stack is as follows:
- > UIProcess process - [AnyInstance webView: didCommitNavigation:] WebKit::NavigationState::NavigationClient::didCommitNavigation (IPC) WebKit::WebPageProxy::didCommitLoadForFrame -> WebContent process (IPC) Messages: : WebPageProxy: : DidCommitLoadForFrame its: : WebFrameLoaderClient: : dispatchDidCommitLoad WebCore::FrameLoader::dispatchDidCommitLoad WebCore::FrameLoader::receivedFirstDataCopy the code
After receiving the page data for the first time, the page history stack and other states are processed and finally thrown to the public proxy. For changing the hash of a page to open another page in the same Document, FrameLoader is the place that handles page loading, which is supposed to be a branch of code that handles whether the target page is the same Document or not. A scan turns up a suspicious function:
void FrameLoader::loadItem(...) {... if (sameDocumentNavigation) loadSameDocumentItem(item); else loadDifferentDocumentItem(item, fromItem, loadType, MayAttemptCacheOnlyLoadForFormSubmissionItem, shouldTreatAsContinuingLoad); }Copy the code
Trace function invocation chain, found – webView: didCommitNavigation: the call stack from the else branch, to check if the processing of branches, ultimately through a process of IPC message is sent to the APP, the APP process code implementation is as follows:
void WebPageProxy::didSameDocumentNavigationForFrame(...) {... m_navigationClient->didSameDocumentNavigation(...) ; . } void NavigationState::NavigationClient::didSameDocumentNavigation(...) {... [static_cast<id <WKNavigationDelegatePrivate>>(navigationDelegate.get()) _webView:m_navigationState->m_webView navigation:wrapper(navigation) didSameDocumentNavigation:toWKSameDocumentNavigationType(navigationType)]; }Copy the code
NavigationDelegate is associated with WKWebView’s public navigationDelegate, and the proxy method lies in the private proxy method list:
typedef NS_ENUM(NSInteger, _WKSameDocumentNavigationType) { _WKSameDocumentNavigationTypeAnchorNavigation, _WKSameDocumentNavigationTypeSessionStatePush, _WKSameDocumentNavigationTypeSessionStateReplace, _WKSameDocumentNavigationTypeSessionStatePop,} WK_API_AVAILABLE (macos (10.10), the ios (8.0)); @protocol WKNavigationDelegatePrivate <WKNavigationDelegate> ... - (void)_webView:(WKWebView *)webView navigation:(WKNavigation *)navigation didSameDocumentNavigation:(_WKSameDocumentNavigationType)navigationType; . @endCopy the code
Rough analysis of the source code, when the enumeration is _WKSameDocumentNavigationTypeAnchorNavigation navigationType means to complete the page change, change the hash. Implementing this private agent has no side effects from the source code, MR documented here: bugs.webkit.org/show_bug.cg… .
conclusion
So only need in WKWebView navigationDelegate belongs to class the following implementation _webView: navigation: didSameDocumentNavigation: Method can capture the change the hash page switching operation, and – webView: didCommitNavigation: matching can complete perception WKWebView page switching to finish time.