Overview
Previously, UIWebView
was mainly used for page loading, but UIWebView
has many problems, and it has been officially abandoned by Apple in 2020. So this article mainly explains WKWebView
, WKWebView
from iOS8
, now most App
should not support iOS7
.
UIWebView
has two problems, one is that the memory consumption is relatively large, and the other is that the performance is poor. WKWebView
with UIWebView
UIWebView
much better performance than 0617f513e201e7, and the refresh rate can reach 60FPS
. The memory footprint is also smaller than UIWebView
.
WKWebView
is a multi-process component. Network
and UI Render
are all completed in independent processes.
Since WKWebView
and App
are not in the same process, if the WKWebView
process crashes, it will not cause the application to crash. It is just an exception such as a blank page. Page loading, rendering and other operations that consume memory and performance are WKWebView
, and after processing, the results are passed to the App
for display, so the performance consumption of the process of App
Web page loading process
- Request the server by domain name, the browser will do a
DNS
resolution before requesting, andIP
address of 0617f513e20331 to the browser. - The browser uses the
IP
request the server and starts the handshake process.TCP
is a three-way handshake. If you usehttps
you also need toTLS
a handshake of 0617f513e20371. After the handshake, you can choose whether to keep the connection according to the protocol field. - After the handshake is completed, the browser sends a request to the server to obtain the
html
file. - The server parses the request, and the
CDN
server returns the corresponding resource file. html
file returned by the server and sends it to thehtml
parser for analysis.- When parsing
html
xml
tag is parsed from top to bottom. During the process, ifcss
or resource file is encountered, it will be loaded asynchronously. Whenjs
html
parsing task will be suspendedjs
and return to continue parsing. Because thejs
file may modify theDOM
- After parsing
html
and executing thejs
, the finalDOM
tree is formed. Find out the final display style of each node throughDOM
css
file, and submit it to the browser for rendering and display - End the link.
Proxy method
WKWebView
and UIWebView
have undergone some changes, and WKWebView
has been more refined. For example, after UI
ends the request, it will be rendered to webView
immediately. WKWebView
will call back a proxy method before rendering to the screen, and the proxy method determines whether to render to the screen. In this way, you can do a check on the requested data to prevent the data from being changed, or to verify whether the view is allowed to be displayed on the screen.
In addition, WKWebView
has some more customized operations compared to UIWebView
- The redirection callback can get this operation when the redirection is requested.
- When the
WKWebView
process exits abnormally, it can be obtained through the callback. - Customize the handling of certificates.
- The deeper
UI
custom operation, thealert
operations such asUI
, etc., are handed over to the native level for processing, and theUI
schemeUIAlertView
is directly displayed bywebView
WKUIDelegate
WKWebView
transfers a lot UI
to the native level for processing, such as the display of pop-up windows or input boxes. In this way, if there is a uniformly defined pop-up window in the project, you can directly call the custom pop-up window instead of only displaying the system pop-up window.
In WKWebView
, the system hands the display of the pop-up window to the client to control. The client can obtain the display information of the pop-up window through the following callback method, and the client can call UIAlertController
to display it. There is a parameter completionHandler
callback block
, need to be sure to call the client, if you do not call it will crash.
- (void)webView:(WKWebView *)webView runJavaScriptAlertPanelWithMessage:(NSString *)message initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(void))completionHandler;
Sometimes H5
will require the user to enter some input, such as username and password. The client can obtain the input box event through the following method, and the client displays the input box. After the user input is completed, the result will be completionHandler
back to 0617f513e207b9.
- (void)webView:(WKWebView *)webView runJavaScriptTextInputPanelWithPrompt:(NSString *)prompt defaultText:(nullable NSString *)defaultText initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(NSString * _Nullable result))completionHandler;
WKNavigationDelegate
The methods related to the loading process are abstracted into WKNavigationDelegate
. Here are a few more commonly used methods to talk about.
The following method decisionHandler
callback, which indicates whether the page is allowed to load. The domain name can be judged here, if it is an off-site domain name, the user can be prompted whether to redirect. If a jump is another App
or store URL
, you can openURL
jump, and the request is intercepted. The processing including cookie
is also completed in this method, and the processing cookie
In addition, many logical processing before the page is displayed are also completed in this method. But it should be noted that, do not do too much time-consuming processing in the method, which will affect the page loading speed.
- (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler;
Start loading the page and request the server.
- (void)webView:(WKWebView *)webView didStartProvisionalNavigation:(null_unspecified WKNavigation *)navigation;
When the page fails to load, this method will be called back, including timeout
such as 0617f513e208e4. On this page, you can display error pages, clear the progress bar, reset the network indicator, and other operations. It should be noted that this method will also be executed when goBack
error
by the status of NSURLErrorCancelled
to determine whether it is 0617f513e208ea.
- (void)webView:(WKWebView *)webView didFailProvisionalNavigation:(WKNavigation *)navigation withError:(NSError *)error;
When the page is loaded and rendered, this method will be called. When this method is called, the H5
of dom
has been parsed and rendered and displayed on the screen. So in this method, some loading operations can be performed, such as removing the progress bar, resetting the network indicator, and so on.
- (void)webView:(WKWebView *)webView didFinishNavigation:(null_unspecified WKNavigation *)navigation;
WKUserContentController
Callback
The interactions between WKWebView
and js
WKUserContentController
by 0617f513e209b1, which will be collectively referred to as userContent
.
If you need to receive and process js
call by calling addScriptMessageHandler:name:
method, and pass a realization WKScriptMessageHandler
the object of the agreement, can receive js
callback, due userContent
will be a strong reference to the object passed, so it should be to create a new object Instead of self
. When registering an object, the following name
is the name of the function called by js
WKUserContentController *userContent = [[WKUserContentController alloc] init];
[userContent addScriptMessageHandler:[[WKWeakScriptMessageDelegate alloc] initWithDelegate:self] name:@"clientCallback"];
In dealloc
, the following method should be used to remove the processing name
[userContent removeScriptMessageHandlerForName:@"clientCallback"];
H5
can initiate a call to the client through the following code. The call is to pass a json
postMessage
function, and the transfer character needs to be added. After the client receives the call, it obtains the body
WKScriptMessage
object passed in by the callback method, and then parses the passed parameters.
window.webkit.messageHandlers.clientCallback.postMessage("{\"funName\":\"getMobileCode\",\"value\":\"srggshqisslfkj\"}");
transfer
The method of calling H5
is the same, creating a WKUserScript
object and passing in the js
code as a parameter. In addition to calling the js
, you can also inject code through this method to change the page dom
, but this is a large amount of code and it is not recommended to do so.
WKUserScript *wkcookieScript = [[WKUserScript alloc] initWithSource:self.javaScriptString
injectionTime:WKUserScriptInjectionTimeAtDocumentStart
forMainFrameOnly:NO];
[webView.configuration.userContentController addUserScript:wkcookieScript];
WKUserScript vs evaluateJavaScript
WKWebView
for performing js
code provides two ways, by userContent
adding a WKUserScript
embodiment the object, and by webView
of evaluateJavaScript:completionHandler:
embodiment, injection js
code.
NSString *removeChildNode = @""
"var header = document.getElementsByTagName:('header')[0];"
"header.parentNote.removeChild(header);"
[self.webView evaluateJavaScript:removeChildNode completionHandler:nil];
The first thing to note is that both methods can inject the js
code, but I haven't studied its internal implementation in depth. The WebKit
kernel is open source, and interested students can take a look. However, there are still some functional differences between the two methods. The API
Let me talk about the evaluateJavaScript:completionHandler:
method. This method is generally performed after the page is displayed js
and get the return value. Of course, it can also be used to inject a section of js
code, but you need to control the injection timing yourself.
WKUserScript
can control the timing of injection. You can js
document
whether 0617f513e20c54 is loaded or not. And whether the injected js
is valid on the current page or including its subpages. Compared with the evaluateJavaScript:
method, this method cannot get js
, so the two methods are still different in function.
Container design
Design ideas
WKWebView
is not used directly in the project, but through a layer of packaging, it becomes a WKWebViewController
handed over to the business layer for use. When designing webViewVC
, you should follow a simple and flexible design. It only provides display functions and does not involve any business logic. It provides external functions such as displaying the navigation bar, setting the title, and the progress bar, which can be assigned WKWebViewConfiguration
and passed in when WKWebViewController
js
interaction, webView
life cycle, loading error, etc. to the caller, and the external connection is handled through the corresponding callback. These callbacks are optional, and if they are not implemented, the webView
will not be affected. The following is an example code, you can also split different types of callbacks to define different agents.
@protocol WKWebViewControllerDelegate <NSObject>
@optional
- (void)webViewDidStartLoad:(WKWebViewController *)webViewVC;
- (void)webViewDidFinishLoad:(WKWebViewController *)webViewVC;
- (void)webView:(WKWebViewController *)webViewVC didFailLoadWithError:(NSError *)error;
- (void)webview:(WKWebViewController *)webViewVC closeWeb:(NSString *)info;
- (void)webview:(WKWebViewController *)webViewVC login:(NSDictionary *)info;
- (void)webview:(WKWebViewController *)webViewVC jsCallbackParams:(NSDictionary *)params;
@end
In addition, WKWebViewController
should also be responsible for handling public parameters, and can be extended based on public parameters. Here we define a method that can specify the position of the basic parameters, which is added by URL
splicing, header
, js
injection, etc. This enumeration is multi-selected, that is, it can be injected at multiple locations. In addition to the basic parameters, you can also add custom parameters, which will also be added to the specified location.
- (void)injectionParamsType:(SVParamsType)type additionalParams:(NSDictionary *)additionalParams;
Reuse pool
WKWebView
initialized for the first time, it will start the webKit
kernel first, and there are some initialization operations, this operation is very performance-consuming. Therefore, the first step in the design of the reuse pool is to initialize a global WKWebView
App
started.
And, create two pools, create visiblePool
store the in-use ones, and create reusablePool
store the idle state. In addition, when the page exits, the page should be recycled and the data on the page should be reclaimed while loading visiblePool
reusablePool
When you need to initialize a webView
container, reusablePool
and put it into visiblePool
. Through the realization of the reuse pool, the time from initializing a webView
container to displaying the page can be reduced.
WKProcessPool
In WKWebView
defined in processPool
property, you can specify the corresponding process pool object. Each webView
has its own content process, if not specified, it will default to a new content process. The content process includes some local cookie
, resources, etc. If they are not in a content process, these data cannot be shared.
You can create a public WKProcessPool
, which is a singleton object. When all webView
created, they use the same content process to realize resource sharing.
UserAgent
User-Agent
is a request header field in the http
protocol to inform the server of some information. User-Agent
contains many fields, such as system version, browser kernel version, network environment, etc. This field can be directly provided by the system, or other fields can be added on the basis of the User-Agent
For example, the following is webView
obtained User-Agent
.
Mozilla/5.0 (iPhone; CPU iPhone OS 10_3_2 like Mac OS X) AppleWebKit/603.2.4 (KHTML, like Gecko) Mobile/14F89
In iOS9
after providing a customUserAgent
property directly WKWebView
provided User-Agent
, and iOS9
required by prior js
to embodiment writing H5
injection User-Agent
.
letter of agreement
A well-designed WebView
container should have good mutual communication functions, and be flexible and expandable. H5
and the client mainly has the following scenarios.
js
calls the client, andjs
calls the client to get the client'scallback
callback and parameters.- The client calls
js
andcallback
callback and parameters afterjs
- The client proactively notified
H5
of some changes in the client's life cycle. For example, enter the lock screen and enter the system life cycle of the front desk.
Taking js
call the client as an example, there are two latitude calls. You can URLRouter
, which can be called up by following the client's URL
definition, and it supports parameter transfer. You can also make page-level calls userContentController
webView
, calling up the login function, etc., that is, js
. This method requires the client to provide the corresponding processing code.
Call each other between the two, try to avoid high-frequency calls, and generally there is no need for high-frequency calls. However, if a high-frequency call of the same function occurs, you need to set a actionID
to distinguish different calls to ensure that they can be distinguished normally when a callback occurs.
callback
can also be passed through parameters. This method is more flexible. If it is fixed, there will be version restrictions. Earlier versions of the client may not support this callback.
Handle callback
In addition to the basic calls of webView
refresh
refreshing the current page, close
closing the current page, etc., the call is directly handled by the corresponding function class, and the other time should be handed over to the outside for processing.
The design scheme here is not that one event corresponds to one callback method, and then the outside world follows the proxy and implements multiple proxy methods. Instead, each callback event is encapsulated into an object, and this object is directly called back to the outside world for processing, so that it is more flexible and the outside world can obtain more information. The definition of the event model can refer to the following.
@interface WKWebViewCallbackModel : NSObject
@property(nonatomic, strong) WKWebViewController *webViewVC;
@property(nonatomic, strong) WKCallType *type;
@property(nonatomic, copy) NSDictionary *parameters;
@property(nonatomic, copy) NSString *callbackID;
@property(nonatomic, copy) NSString *callbackFunction;
@end
Persistence
Currently H5
persistence solution pages, mainly WebKit
comes localStorage
and Cookie
, but Cookie
not used for persistence operations, it should not be given H5
used for persistence. If you want to be more stable persistence, you may consider providing a js bridge
of CRUD
interface that allows H5
can be used to store and query data.
The persistence solution adopts the same solution as the client, and a separate data table can be H5
Caching mechanism
Caching rules
Front-end browsers, including WKWebView
, will cache resources in order to ensure quick page opening and reduce user traffic consumption. This caching rule WKWebView
. If we want to ensure that the resource files are up-to-date each time, we can also choose not to use the cache, but we generally don't do this.
NSURLRequestUseProtocolCachePolicy = 0
, the default cache strategy, is the same as the cache performance of theSafari
NSURLRequestReloadIgnoringLocalCacheData = 1,
ignores the local cache and obtains data directly from the server.NSURLRequestReturnCacheDataElseLoad = 2
, if there is a local cache, use the cache, otherwise load the server data. This strategy does not verify whether the cache expires.NSURLRequestReturnCacheDataDontLoad = 3
, only obtained from the local, and does not judge the validity and whether it is changed. If there is no local, the server data will not be requested, and the request will fail.NSURLRequestReloadIgnoringLocalAndRemoteCacheData = 4
, ignoring the local and routing caches, and get the latest data from the server.NSURLRequestReloadRevalidatingCacheData = 5
, verify that the cache is available from the server, and request data from the server if it is not available locally.NSURLRequestReloadIgnoringCacheData = NSURLRequestReloadIgnoringLocalCacheData
,
According to Apple's default caching strategy, a three-step check will be performed.
- Whether the cache exists.
- Verify that the cache is out of date.
- Whether the cache has changed.
Cache file
iOS9
Apple provides the cache management class WKWebsiteDataStore
, which can query and delete the specified type of cache files on the disk. Because many App
are iOS9
, it is highly recommended to use this API
to manage the local cache, as well as cookie
. The local file cache types are defined as the following, the commonly used ones are mainly cookie
, diskCache
, memoryCache
.
WKWebsiteDataTypeFetchCache
, the cache in the disk, according to the source code, the type isDOMCache
WKWebsiteDataTypeDiskCache
, the local disk cache, which is different from the implementation offetchCache
WKWebsiteDataTypeMemoryCache
, local memory cacheWKWebsiteDataTypeOfflineWebApplicationCache
, offlineweb
application cacheWKWebsiteDataTypeCookies
,cookie
cacheWKWebsiteDataTypeSessionStorage
,html
session storageWKWebsiteDataTypeLocalStorage
,html
local data cacheWKWebsiteDataTypeWebSQLDatabases
,WebSQL
database dataWKWebsiteDataTypeIndexedDBDatabases
, database indexWKWebsiteDataTypeServiceWorkerRegistrations
, server registration data
You can get all the local cache file types through the following method, and the returned collection string is the type defined above.
+ (NSSet<NSString *> *)allWebsiteDataTypes;
You can specify to delete the specified type of data within a certain period of time, and the callback will be block
after deletion.
- (void)removeDataOfTypes:(NSSet<NSString *> *)dataTypes modifiedSince:(NSDate *)date completionHandler:(void (^)(void))completionHandler;
The system also provides a more customized method. Obtain all WKWebsiteDataRecord
fetchDataRecordsOfTypes:
method. This object contains two parameters: domain name and type. You can judge based on the domain name and type, and then call the removeDataOfTypes:
method to pass in the object to be deleted, and delete the data under the specified domain name.
// 获取
- (void)fetchDataRecordsOfTypes:(NSSet<NSString *> *)dataTypes completionHandler:(void (^)(NSArray<WKWebsiteDataRecord *> *))completionHandler;
// 删除
- (void)removeDataOfTypes:(NSSet<NSString *> *)dataTypes forDataRecords:(NSArray<WKWebsiteDataRecord *> *)dataRecords completionHandler:(void (^)(void))completionHandler;
http caching strategy
When the client H5
, page caching problems often occur. H5
often say "try to clear the cache". In fact, the reason for this problem is that there is a problem with the cache management strategy H5
Here to talk about the cache management strategy of H5
The cache management of H5
http
protocol. The more commonly used method is the Cache-Control
and Last-Modified
.
Cache-Control
: The effective duration of the file cache. For example, the server response header returnsCache-Control:max-age=600
after requesting the file, which means that the effective duration of the file is600
seconds. Therefore, this file will not issue a network request within the validity period until it expires.Last-Modified
: The response header returned by the server after requesting the file indicates the latest update time of the file. IfCache-Control
expires, it will request the server and put this time in theIf-Modified-Since
field of the request header. The server will compare the time after receiving the request. If the time has not changed, it will return304
, otherwise it will return a new file and response header field. , And return200
.
Cache-Control
is from http1.1
, indicating the relative effective duration of the file. Before this, there is a Expires
, indicating the absolute effective duration of the file, for example, Expires: Thu, 10 Nov 2015 08:45:11 GMT
, both of which can be used.
Last-Modified
also has a similar field Etag
, the difference is that Last-Modified
is compared with the time, and Etag
is compared with the hash value of the file. When the validity period of the file expires, the requesting server will Etag
If-None-Match
field of the request header and submit it to the server for comparison.
Cookie handling
As we all know, the http
protocol supports the cookie
. The server can set the browser to cookie
Set-Cookie:
field, and can also specify the expiration time, domain name, etc. These are more applicable in browsers such as Chrome
, but if it is displayed in the client, the client needs to pass some parameters, so that H5
can get the login status.
Although Apple provides some Cookie
managed by API
, there WKWebView
in the use of 0617f513e34576. Finally, I will give a more general solution.
WKWebView Cookie Design
When using UIWebView
before, it reads an area with the traditional cookie
management class NSHTTPCookieStorage
UIWebView
of cookie
is also managed by this class. However, the WKWebView
cookie
not the same. cookie
App
of 0617f513e345e1, so the two need to be processed separately.
WKWebView
of cookie
and NSHTTPCookieStorage
also between synchronous operation, but the synchronization significant delay, but not easy to rule pondering. So for the stability of the code, it is more appropriate to cookie
WK
and app
are two processes, cookie
is two, but WK
of cookie
in app
sandbox of. There is a timing synchronization, but there is no specific rule, so it is best not to rely on synchronization. WK
are only two opportunities for the cookie
change of 0617f513e3580f, one is for js
execute code setCookie
, and the other is for response
to return to cookie
.
WKWebsiteDataStore
Cookie
management has always been WKWebView
a drawback, for the Cookie
inconvenient process. In iOS9
, you can Cookie
WKWebsiteDataStore
, but it is not intuitive to use, you need to filter and delete dataType
Moreover, WKWebsiteDataStore
does not have the function of adding, so cookie
can only be deleted, and cookie
cannot be added.
if (@available(iOS 9.0, *)) {
NSSet *cookieTypeSet = [NSSet setWithObject:WKWebsiteDataTypeCookies];
[[WKWebsiteDataStore defaultDataStore] removeDataOfTypes:cookieTypeSet modifiedSince:[NSDate dateWithTimeIntervalSince1970:0] completionHandler:^{
}];
}
WKHTTPCookieStore
In iOS11
in Apple WKWebsiteDataStore
based on its increased WKHTTPCookieStore
class specifically cookie
processing, and support for add, delete, query three operations, you can also register a observer
to cookie
changes to monitor, when cookie
after change Notify the listener through the callback method.
WKWebsiteDataStore
can get H5
page by document.cookie
way of writing cookie
, as well as a server by Set-Cookie
way of writing cookie
, so it is still very recommended to use this class to manage cookie
, but unfortunately only supports iOS11
.
Below is a piece of code to add cookie
WKWebView
NSMutableDictionary *params = [NSMutableDictionary dictionary];
[params setObject:@"password" forKey:NSHTTPCookieName];
[params setObject:@"e10adc3949ba5" forKey:NSHTTPCookieValue];
[params setObject:@"www.google.com" forKey:NSHTTPCookieDomain];
[params setObject:@"/" forKey:NSHTTPCookiePath];
[params setValue:[NSDate dateWithTimeIntervalSinceNow:60*60*72] forKey:NSHTTPCookieExpires];
NSHTTPCookie *cookie = [NSHTTPCookie cookieWithProperties:params];
[self.cookieWebview.configuration.websiteDataStore.httpCookieStore setCookie:cookie completionHandler:nil];
My company plan
Processing Cookie
best way is through WKHTTPCookieStore
to deal with, but it only supports iOS11
and more equipment, so this program is still not as our choice. The second is WKWebsiteDataStore
, but it can only be used as a delete cookie
, and it cannot be used to manage cookie
.
Our approach is that by iOS8
launched WKUserContentController
to manage webView
of cookie
by NSHTTPCookieStorage
to manage network requests cookie
, for example H5
request made. NSURLConnection
sent through NSURLSession
and 0617f513e36308 will default to NSHTTPCookieStorage
in cookie
, and H5
within 0617f513e3630e will also be handed over to NSURLSession
by the system for processing.
At the level of code implementation, monitor the didFinishLaunching
notification, and request user-related information from the server when the program starts. Of course, it can also be taken locally, all of which are the same. Data are key
, value
issued form according key=value
form of stitching, by document.cookie
assembled into a set cookie
of js
codes, all the code string of splicing a semicolon separated, behind to webView
species cookie
time to time by the character String execution.
cookie
requested by the network, if you use NSHTTPCookieStorage
directly transfer cookie
to the root domain name, it can take effect for all subdomains under the root domain name. The processing here is relatively simple.
SVREQUEST.type(SVRequestTypePost).parameters(params).success(^(NSDictionary *cookieDict) {
self.cookieData = [cookieDict as:[NSDictionary class]];
[self addCookieWithDict:cookieDict forHost:@".google.com"];
[self addCookieWithDict:cookieDict forHost:@".google.cn"];
[self addCookieWithDict:cookieDict forHost:@".google.jp"];
NSMutableString *scriptString = [NSMutableString string];
for (NSString *key in self.cookieData.allKeys) {
NSString *cookieString = [NSString stringWithFormat:@"%@=%@", key, cookieDict[key]];
[scriptString appendString:[NSString stringWithFormat:@"document.cookie = '%@;expires=Fri, 31 Dec 9999 23:59:59 GMT;';", cookieString]];
}
self.webviewCookie = scriptString;
}).startRequest();
- (void)addCookieWithDict:(NSDictionary *)dict forHost:(NSString *)host {
[dict enumerateKeysAndObjectsUsingBlock:^(NSString * _Nonnull key, NSString * _Nonnull value, BOOL * _Nonnull stop) {
NSMutableDictionary *properties = [NSMutableDictionary dictionary];
[properties setObject:key forKey:NSHTTPCookieName];
[properties setObject:value forKey:NSHTTPCookieValue];
[properties setObject:host forKey:NSHTTPCookieDomain];
[properties setObject:@"/" forKey:NSHTTPCookiePath];
[properties setValue:[NSDate dateWithTimeIntervalSinceNow:60*60*72] forKey:NSHTTPCookieExpires];
NSHTTPCookie *cookie = [NSHTTPCookie cookieWithProperties:properties];
[[NSHTTPCookieStorage sharedHTTPCookieStorage] setCookie:cookie];
}];
}
Of webView
species cookie
by WKUserContentController
writing js
embodiment implemented, i.e. splicing above js
string. But this class has a persistent problem that can not cookie
, which is cookie
with userContentController
statement cycle, if the exit App
the cookie
will disappear next time you enter App
need species also once, which is a big problem.
Therefore, our company's processing method is decidePolicyForNavigationAction:
callback method. The code will determine whether the domain name has been seeded with cookie
, if not, type cookie
. For cookie
process, I created a new cookieWebview
deal specifically cookie
problems when performing addUserScript
later, by loadHTMLString:baseURL:
load an empty local html
, and domain name to be currently the domain name of the page, so that just kind of cookie
current processPool
all within webView
effect.
This kind of scheme cookie
is executed synchronously, and has webView
impact on 0617f513e36540. After my test, adding cookie
average only takes 28ms time. From the user's point of view, it is imperceptible, and there will be no page freeze or refresh.
- (void)setCookieWithUrl:(NSURL *)url {
NSString *host = [url host];
if ([self.cookieURLs containsObject:host]) {
return;
}
[self.cookieURLs addObject:host];
WKUserScript *wkcookieScript = [[WKUserScript alloc] initWithSource:self.webviewCookie
injectionTime:WKUserScriptInjectionTimeAtDocumentStart
forMainFrameOnly:NO];
[self.cookieWebview.configuration.userContentController addUserScript:wkcookieScript];
NSString *baseWebUrl = [NSString stringWithFormat:@"%@://%@", url.scheme, url.host];
[self.cookieWebview loadHTMLString:@"" baseURL:[NSURL URLWithString:baseWebUrl]];
}
The process of deleting cookie
is relatively simple. NSHTTPCookieStorage
traverses through the cookies
NSHTTPCookie
that you need to delete, and then you can delete it by calling the method. webView
is simple and rude, just call removeAllUserScripts
delete all WKUserScript
.
- (void)removeWKWebviewCookie {
self.webviewCookie = nil;
[self.cookieWebview.configuration.userContentController removeAllUserScripts];
NSMutableArray<NSHTTPCookie *> *cookies = [NSMutableArray array];
[[NSHTTPCookieStorage sharedHTTPCookieStorage].cookies enumerateObjectsUsingBlock:^(NSHTTPCookie * _Nonnull cookie, NSUInteger idx, BOOL * _Nonnull stop) {
if ([self.cookieData.allKeys containsObject:cookie.name]) {
[cookies addObjectOrNil:cookie];
}
}];
[cookies enumerateObjectsUsingBlock:^(NSHTTPCookie * _Nonnull cookie, NSUInteger idx, BOOL * _Nonnull stop) {
[[NSHTTPCookieStorage sharedHTTPCookieStorage] deleteCookie:cookie];
}];
}
White screen problem
If WKWebView
loads a page that takes up too much memory, it will cause the WebContent Process
process to crash, and then a white screen will appear on the page. It may also be caused by other processes in the system occupying too much memory. There are two solutions to the white screen problem caused by low memory.
In iOS9
, Apple introduced the following API
. When the WebContent
process exits abnormally, it will call back this API
. Corresponding processing can be performed in this API
, such as displaying an abnormal page.
- (void)webViewWebContentProcessDidTerminate:(WKWebView *)webView;
If returning from other App
causes a white screen problem, you can judge whether webView.title
is empty when the view is about to be displayed. If it is empty, the abnormal page will be displayed.
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。