UIWebView & WKWebView 詳解下

前言

一直想系統(tǒng)的總結(jié)下UIWebViewWKWebView,這里整理了一個
Demo可供參考

分為兩部分:
UIWebView & WKWebView 上
UIWebView & WKWebView 下

簡介

WKWebView是Apple于iOS 8.0推出的WebKit中的核心控件,用來替代UIWebView。WKWebViewUIWebView的優(yōu)勢在于:

  • 更多的支持HTML5的特性
  • 高達60fps的滾動刷新率以及內(nèi)置手勢
  • 與Safari相同的JavaScript引擎
  • 將UIWebViewDelegate與UIWebView拆分成了14類與3個協(xié)議(官方文檔說明
  • 可以獲取加載進度:estimatedProgress(UIWebView需要調(diào)用私有Api)

POST請求

WKWebView相關(guān)的post請求實現(xiàn)

Html實現(xiàn)

<html>
    <head>
        <script>
            //調(diào)用格式: post('URL', {"key": "value"});
            function post(path, params) {
                var method = "post";
                var form = document.createElement("form");
                form.setAttribute("method",method);
                form.setAttribute("action",path);
                
                for(var key in params) {
                    if(params.hasOwnProperty(key)) {
                        var hiddenField = document.createElement("input");
                        hiddenField.setAttribute("type","hidden");
                        hiddenField.setAttribute("name",key);
                        hiddenField.setAttribute("value",params[key]);
                        
                        form.appendChild(hiddenField);
                    }
                }
                document.body.appendChild(form);
                form.submit();
            }
        </script>
    </head>
    <body>
    </body>
</html>

OC中代碼實現(xiàn):
思路:
1 、將一個包含JavaScript的POST請求的HTML代碼放到工程目錄中
2 、加載這個包含JavaScript的POST請求的代碼到WKWebView
3 、加載完成之后,用Native調(diào)用JavaScript的POST方法并傳入?yún)?shù)來完成請求

//僅當(dāng)?shù)谝淮蔚臅r候加載本地JS
// @property(nonatomic,assign) BOOL needLoadJSPOST;

- (void)viewDidLoad
{
     // JS發(fā)送POST的Flag,為真的時候會調(diào)用JS的POST方法
    self.needLoadJSPOST = YES;
    //POST使用預(yù)先加載本地JS方法的html實現(xiàn),請確認(rèn)WKJSPOST存在
    [self loadHostPathURL:@"WKJSPOST"];
}

- (void)loadHostPathURL:(NSString *)url
{
    //獲取JS所在的路徑
    NSString *path = [[NSBundle mainBundle] pathForResource:url ofType:@"html"];
    //獲得html內(nèi)容
    NSString *html = [[NSString alloc] initWithContentsOfFile:path encoding:NSUTF8StringEncoding error:nil];
    //加載js
    [self.webView loadHTMLString:html baseURL:[[NSBundle mainBundle] bundleURL]];
}

//加載成功,對應(yīng)UIWebView的- (void)webViewDidFinishLoad:(UIWebView *)webView; 網(wǎng)頁加載完成,導(dǎo)航的變化
- (void)webView:(WKWebView *)webView didFinishNavigation:(WKNavigation *)navigation
{
    /*
     主意:這個方法是當(dāng)網(wǎng)頁的內(nèi)容全部顯示(網(wǎng)頁內(nèi)的所有圖片必須都正常顯示)的時候調(diào)用(不是出現(xiàn)的時候就調(diào)用),,否則不顯示,或則部分顯示時這個方法就不調(diào)用。
     */
    // 判斷是否需要加載(僅在第一次加載)
    if (self.needLoadJSPOST) {
        // 調(diào)用使用JS發(fā)送POST請求的方法
        [self postRequestWithJS];
        // 將Flag置為NO(后面就不需要加載了)
        self.needLoadJSPOST = NO;
    }
}

#pragma mark - JSPOST
// 調(diào)用JS發(fā)送POST請求
- (void)postRequestWithJS
{
    // 拼裝成調(diào)用JavaScript的字符串
    NSString *jscript = [NSString stringWithFormat:@"post('%@',{%@})",self.URLString,self.postData];
    NSLog(@"Javascript: %@", jscript);
    //post('http://www.postexample.com',{"username":"aaa","password":"123"})
    // 調(diào)用JS代碼
    [self.webView evaluateJavaScript:jscript completionHandler:^(id object, NSError * _Nullable error) {
        NSLog(@"%@",error);
    }];
}

UIWebView的post請求實現(xiàn)

- (void)viewDidLoad {
    [super viewDidLoad];
    NSURL*url=[NSURL URLWithString:@"http://your_url.com"];
    NSString*body=[NSString stringWithFormat:@"arg1=%@&arg2=%@",@"val1",@"val2"];
    NSMutableURLRequest*request=[[NSMutableURLRequest alloc]initWithURL:url];
    [request setHTTPMethod:@"POST"];
    [request setHTTPBody:[body dataUsingEncoding:NSUTF8StringEncoding]];
    [self.webView loadRequest:request];
}

Cookie相關(guān)

WKWebView的cookie管理

比起UIWebView的自動管理,WKWebViewCookie管理坑還是比較多的,注意事項如下:
1、WKWebView加載網(wǎng)頁得到的Cookie會同步到NSHTTPCookieStorage
2、WKWebView加載請求時,不會同步NSHTTPCookieStorage中已有的Cookie
3、通過共用一個WKProcessPool并不能解決2中Cookie同步問題,且可能會造成Cookie丟失。

添加cookie

動態(tài)注入js

WKUserContentController *UserContentController = [[WKUserContentController alloc] init];
 //添加自定義的cookie
WKUserScript *newCookieScript = [[WKUserScript alloc] initWithSource:@"document.cookie = 'SyhCookie=Syh;'" injectionTime:WKUserScriptInjectionTimeAtDocumentStart forMainFrameOnly:NO];
//添加腳本
 [UserContentController addUserScript:newCookieScript];
WKWebView執(zhí)行js添加cookie.png

解決后續(xù)Ajax請求Cookie丟失問題

添加WKUserScript,需保證sharedHTTPCookieStorage中你的Cookie存在。

/*!
 *  更新webView的cookie
 */
- (void)updateWebViewCookie
{
    WKUserScript * cookieScript = [[WKUserScript alloc] initWithSource:[self cookieString] injectionTime:WKUserScriptInjectionTimeAtDocumentStart forMainFrameOnly:NO];
    //添加Cookie
    [self.configuration.userContentController addUserScript:cookieScript];
}

- (NSString *)cookieString
{
    NSMutableString *script = [NSMutableString string];
    [script appendString:@"var cookieNames = document.cookie.split('; ').map(function(cookie) { return cookie.split('=')[0] } );\n"];
    for (NSHTTPCookie *cookie in [[NSHTTPCookieStorage sharedHTTPCookieStorage] cookies]) {
        // Skip cookies that will break our script
        if ([cookie.value rangeOfString:@"'"].location != NSNotFound) {
            continue;
        }
        // Create a line that appends this cookie to the web view's document's cookies
        [script appendFormat:@"if (cookieNames.indexOf('%@') == -1) { document.cookie='%@'; };\n", cookie.name, cookie.da_javascriptString];
    }
    return script;
}

@interface NSHTTPCookie (Utils)

- (NSString *)da_javascriptString;

@end

@implementation NSHTTPCookie (Utils)

- (NSString *)da_javascriptString
{
    NSString *string = [NSString stringWithFormat:@"%@=%@;domain=%@;path=%@",
                        self.name,
                        self.value,
                        self.domain,
                        self.path ?: @"/"];
    if (self.secure) {
        string = [string stringByAppendingString:@";secure=true"];
    }
    return string;
}

@end

解決跳轉(zhuǎn)新頁面時Cookie帶不過去問題

當(dāng)你點擊頁面上的某個鏈接,跳轉(zhuǎn)到新的頁面,Cookie又丟了,需保證sharedHTTPCookieStorage中你的Cookie存在。

//核心方法:
/**
 修復(fù)打開鏈接Cookie丟失問題

 @param request 請求
 @return 一個fixedRequest
 */
- (NSURLRequest *)fixRequest:(NSURLRequest *)request
{
    NSMutableURLRequest *fixedRequest;
    if ([request isKindOfClass:[NSMutableURLRequest class]]) {
        fixedRequest = (NSMutableURLRequest *)request;
    } else {
        fixedRequest = request.mutableCopy;
    }
    //防止Cookie丟失
    NSDictionary *dict = [NSHTTPCookie requestHeaderFieldsWithCookies:[NSHTTPCookieStorage sharedHTTPCookieStorage].cookies];
    if (dict.count) {
        NSMutableDictionary *mDict = request.allHTTPHeaderFields.mutableCopy;
        [mDict setValuesForKeysWithDictionary:dict];
        fixedRequest.allHTTPHeaderFields = mDict;
    }
    return fixedRequest;
}

#pragma mark - WKNavigationDelegate 

- (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler {

#warning important 這里很重要
    //解決Cookie丟失問題
    NSURLRequest *originalRequest = navigationAction.request;
    [self fixRequest:originalRequest];
    //如果originalRequest就是NSMutableURLRequest, originalRequest中已添加必要的Cookie,可以跳轉(zhuǎn)
    //允許跳轉(zhuǎn)
    decisionHandler(WKNavigationActionPolicyAllow);
    //可能有小伙伴,會說如果originalRequest是NSURLRequest,不可變,那不就添加不了Cookie了,是的,我們不能因為這個問題,不允許跳轉(zhuǎn),也不能在不允許跳轉(zhuǎn)之后用loadRequest加載fixedRequest,否則會出現(xiàn)死循環(huán),具體的,小伙伴們可以用本地的html測試下。
    
    NSLog(@"%@", NSStringFromSelector(_cmd));
}

#pragma mark - WKUIDelegate

- (WKWebView *)webView:(WKWebView *)webView createWebViewWithConfiguration:(WKWebViewConfiguration *)configuration forNavigationAction:(WKNavigationAction *)navigationAction windowFeatures:(WKWindowFeatures *)windowFeatures {

#warning important 這里也很重要
    //這里不打開新窗口
    [self.webView loadRequest:[self fixRequest:navigationAction.request]];
    return nil;
}

Cookie依然丟失

什么的方法需保證sharedHTTPCookieStorage中你的Cookie存在。怎么保證呢?由于WKWebView加載網(wǎng)頁得到的Cookie會同步到NSHTTPCookieStorage的特點,有時候你強行添加的Cookie會在同步過程中丟失。抓包(Mac推薦Charles)你就會發(fā)現(xiàn),點擊一個鏈接時,Requestheader中多了Set-Cookie字段,其實Cookie已經(jīng)丟了。下面推薦筆者的解決方案,那就是把自己需要的Cookie主動保存起來,每次調(diào)用[NSHTTPCookieStorage sharedHTTPCookieStorage].cookies方法時,保證返回的數(shù)組中有自己需要的Cookie。下面上代碼,用了runtimeMethod Swizzling

首先是在適當(dāng)?shù)臅r候,保存

//比如登錄成功,保存Cookie
NSArray *allCookies = [[NSHTTPCookieStorage sharedHTTPCookieStorage] cookies];
for (NSHTTPCookie *cookie in allCookies) {
    if ([cookie.name isEqualToString:DAServerSessionCookieName]) {
        NSDictionary *dict = [[NSUserDefaults standardUserDefaults] dictionaryForKey:DAUserDefaultsCookieStorageKey];
        if (dict) {
            NSHTTPCookie *localCookie = [NSHTTPCookie cookieWithProperties:dict];
            if (![cookie.value isEqual:localCookie.value]) {
                NSLog(@"本地Cookie有更新");
            }
        }
        [[NSUserDefaults standardUserDefaults] setObject:cookie.properties forKey:DAUserDefaultsCookieStorageKey];
        [[NSUserDefaults standardUserDefaults] synchronize];
        break;
    }
}

在讀取時,如果沒有則添加

@implementation NSHTTPCookieStorage (Utils)

+ (void)load
{
    class_methodSwizzling(self, @selector(cookies), @selector(da_cookies));
}

- (NSArray<NSHTTPCookie *> *)da_cookies
{
    NSArray *cookies = [self da_cookies];
    BOOL isExist = NO;
    for (NSHTTPCookie *cookie in cookies) {
        if ([cookie.name isEqualToString:DAServerSessionCookieName]) {
            isExist = YES;
            break;
        }
    }
    if (!isExist) {
        //CookieStroage中添加
        NSDictionary *dict = [[NSUserDefaults standardUserDefaults] dictionaryForKey:DAUserDefaultsCookieStorageKey];
        if (dict) {
            NSHTTPCookie *cookie = [NSHTTPCookie cookieWithProperties:dict];
            [[NSHTTPCookieStorage sharedHTTPCookieStorage] setCookie:cookie];
            NSMutableArray *mCookies = cookies.mutableCopy;
            [mCookies addObject:cookie];
            cookies = mCookies.copy;
        }
    }
    return cookies;
}

@end

UIWebView的cookie管理

UIWebViewCookie管理很簡單,一般不需要我們手動操作Cookie,因為所有Cookie都會被[NSHTTPCookieStorage sharedHTTPCookieStorage]這個單例管理,而且UIWebView會自動同步CookieStorage中的Cookie,所以只要我們在Native端,正常登陸退出,h5在適當(dāng)時候刷新,就可以正確的維持登錄狀態(tài),不需要做多余的操作。

可能有一些情況下,我們需要在訪問某個鏈接時,添加一個固定Cookie用來做區(qū)分,那么就可以通過header來實現(xiàn)
思路:
1、主動操作NSHTTPCookieStorage,添加一個自定義Cookie
2、讀取所有Cookie
3、Cookie轉(zhuǎn)換成HTTPHeaderFields,并添加到request的header


NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:self.URLString]];
//主動操作NSHTTPCookieStorage,添加一個自定義Cookie
NSHTTPCookie *cookie = [NSHTTPCookie cookieWithProperties:@{
                                                            NSHTTPCookieName: @"customCookieName",
                                                            NSHTTPCookieValue: @"heiheihei",
                                                            NSHTTPCookieDomain: @".baidu.com",
                                                            NSHTTPCookiePath: @"/"

                                                            }];
//Cookie存在則覆蓋,不存在添加
[[NSHTTPCookieStorage sharedHTTPCookieStorage] setCookie:cookie];
//讀取所有Cookie
NSArray *cookies = [NSHTTPCookieStorage sharedHTTPCookieStorage].cookies;
//Cookies數(shù)組轉(zhuǎn)換為requestHeaderFields
NSDictionary *requestHeaderFields = [NSHTTPCookie requestHeaderFieldsWithCookies:cookies];
//設(shè)置請求頭
request.allHTTPHeaderFields = requestHeaderFields;
[self.webView loadRequest:request];

UIWebView自定義cookie.png

自定義瀏覽器UserAgen

這個其實在App開發(fā)中,比較重要。比如常見的微信、支付寶App等,都有自己的UserAgent,而UA最常用來判斷在哪個App內(nèi),一般App的下載頁中只有一個按鈕"點擊下載",當(dāng)用戶點擊該按鈕時,在微信中則跳轉(zhuǎn)到應(yīng)用寶,否則跳轉(zhuǎn)到AppStore。那么如何區(qū)分在哪個App中呢?就是js判斷UA

//js中判斷
if (navigator.userAgent.indexOf("MicroMessenger") !== -1) {
   //在微信中
}

關(guān)于自定義UA,這個UIWebView不提供Api,而WKWebView提供Api,前文中也說明過,就是調(diào)用customUserAgent屬性。

self.webView.customUserAgent = @"WebViewDemo/1.1.0";    //自定義UA,只支持WKWebView

而有沒有其他的方法實現(xiàn)自定義瀏覽器UserAgent呢?有

//最好在AppDelegate中就提前設(shè)置
@implementation AppDelegate


- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    // Override point for customization after application launch.
    
    //設(shè)置自定義UserAgent
    [self setCustomUserAgent];
    return YES;
}

- (void)setCustomUserAgent
{
    //get the original user-agent of webview
    UIWebView *webView = [[UIWebView alloc] initWithFrame:CGRectZero];
    NSString *oldAgent = [webView stringByEvaluatingJavaScriptFromString:@"navigator.userAgent"];
    //add my info to the new agent
    NSString *newAgent = [oldAgent stringByAppendingFormat:@" %@", @"WebViewDemo/1.0.0"];
    //regist the new agent
    NSDictionary *dictionnary = [[NSDictionary alloc] initWithObjectsAndKeys:newAgent, @"UserAgent", newAgent, @"User-Agent", nil];
    [[NSUserDefaults standardUserDefaults] registerDefaults:dictionnary];
}

@end

說明:

1、通過NSUserDefaults設(shè)置自定義UserAgent,可以同時作用于UIWebView和WKWebView。
2、WKWebView的customUserAgent屬性,優(yōu)先級高于NSUserDefaults,當(dāng)同時設(shè)置時,顯示customUserAgent的值。

WKWebView自定義返回/關(guān)閉按鈕

//返回按鈕
@property (nonatomic)UIBarButtonItem* customBackBarItem;
//關(guān)閉按鈕
@property (nonatomic)UIBarButtonItem* closeButtonItem;

- (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler
{
    [self updateNavigationItems];
    //允許跳轉(zhuǎn)
    decisionHandler(WKNavigationActionPolicyAllow);
}
- (void)webView:(WKWebView *)webView didFinishNavigation:(WKNavigation *)navigation
{
    [self updateNavigationItems];
}


- (void)updateNavigationItems
{
    if (self.webView.canGoBack) {
        UIBarButtonItem *spaceButtonItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFixedSpace target:nil action:nil];
        spaceButtonItem.width = -6.5;
        [self.navigationItem setLeftBarButtonItems:@[spaceButtonItem,self.customBackBarItem,self.closeButtonItem] animated:NO];
    }else {
        self.navigationController.interactivePopGestureRecognizer.enabled = YES;
        [self.navigationItem setLeftBarButtonItems:@[self.customBackBarItem]];
    }
}

-(UIBarButtonItem*)customBackBarItem{
    if (!_customBackBarItem) {
        UIImage* backItemImage = [[UIImage imageNamed:@"backItemImage"] imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate];
        UIImage* backItemHlImage = [[UIImage imageNamed:@"backItemImage-hl"] imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate];
        
        UIButton* backButton = [[UIButton alloc] init];
        [backButton setTitle:@"返回" forState:UIControlStateNormal];
        [backButton setTitleColor:self.navigationController.navigationBar.tintColor forState:UIControlStateNormal];
        [backButton setTitleColor:[self.navigationController.navigationBar.tintColor colorWithAlphaComponent:0.5] forState:UIControlStateHighlighted];
        [backButton.titleLabel setFont:[UIFont systemFontOfSize:17]];
        [backButton setImage:backItemImage forState:UIControlStateNormal];
        [backButton setImage:backItemHlImage forState:UIControlStateHighlighted];
        [backButton sizeToFit];
        
        [backButton addTarget:self action:@selector(customBackItemClicked) forControlEvents:UIControlEventTouchUpInside];
        _customBackBarItem = [[UIBarButtonItem alloc] initWithCustomView:backButton];
    }
    return _customBackBarItem;
}

-(void)customBackItemClicked{
    if (self.webView.goBack) {
        [self.webView goBack];
    }else{
        [self.navigationController popViewControllerAnimated:YES];
    }
}

-(UIBarButtonItem*)closeButtonItem{
    if (!_closeButtonItem) {
        _closeButtonItem = [[UIBarButtonItem alloc] initWithTitle:@"關(guān)閉" style:UIBarButtonItemStylePlain target:self action:@selector(closeItemClicked)];
    }
    return _closeButtonItem;
}

-(void)closeItemClicked{
    [self.navigationController popViewControllerAnimated:YES];
}

WKWebView添加進度條

- (void)viewDidLoad 
{
   //設(shè)置加載進度條
  //@property (nonatomic,strong) UIProgressView *progressView;
  //static void *WkwebBrowserContext = &WkwebBrowserContext;
  //添加進度條
   [self.view addSubview:self.progressView];
   [self.webView addObserver:self forKeyPath:NSStringFromSelector(@selector(estimatedProgress)) options:0 context:WkwebBrowserContext];
}

//開始加載,對應(yīng)UIWebView的- (void)webViewDidStartLoad:(UIWebView *)webView;
- (void)webView:(WKWebView *)webView didStartProvisionalNavigation:(null_unspecified WKNavigation *)navigation
{
    //開始加載的時候,讓加載進度條顯示
    self.progressView.hidden = NO;
}


#pragma mark - 進度條
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSKeyValueChangeKey,id> *)change context:(void *)context
{
    if ([keyPath isEqualToString:NSStringFromSelector(@selector(estimatedProgress))] && object == self.webView) {
        self.progressView.alpha = 1.0f;
        BOOL animated = self.webView.estimatedProgress > self.progressView.progress;
        [self.progressView setProgress:self.webView.estimatedProgress animated:animated];
        // Once complete, fade out UIProgressView
        if (self.webView.estimatedProgress >= 1.0f) {
            [UIView animateWithDuration:0.3f delay:0.3f options:UIViewAnimationOptionCurveEaseOut animations:^{
                self.progressView.alpha = 0.0f;
            } completion:^(BOOL finished) {
                [self.progressView setProgress:0.0f animated:NO];
            }];
        }
    }else{
        [super observeValueForKeyPath:keyPath ofObject:object change:change context:context];
    }
}

- (UIProgressView *)progressView{
    if (!_progressView) {
        _progressView = [[UIProgressView alloc]initWithProgressViewStyle:UIProgressViewStyleDefault];
        if (_isNavHidden == YES) {
            _progressView.frame = CGRectMake(0, 20, self.view.bounds.size.width, 3);
        }else{
            _progressView.frame = CGRectMake(0, 64, self.view.bounds.size.width, 3);
        }
        // 設(shè)置進度條的色彩
        [_progressView setTrackTintColor:[UIColor colorWithRed:240.0/255 green:240.0/255 blue:240.0/255 alpha:1.0]];
        _progressView.progressTintColor = [UIColor greenColor];
    }
    return _progressView;
}

WKWebView填坑

js alert方法不彈窗

實現(xiàn)- (void)webView:(WKWebView *)webView runJavaScriptAlertPanelWithMessage:(NSString *)message initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(void))completionHandler;方法,如果不實現(xiàn),就什么都不發(fā)生,好吧,乖乖實現(xiàn)吧,實現(xiàn)了就能彈窗了。

- (void)webView:(WKWebView *)webView runJavaScriptAlertPanelWithMessage:(NSString *)message initiatedByFrame:(WKFrameInfo *)frame completionHandler:(nonnull void (^)(void))completionHandler
{
    //js 里面的alert實現(xiàn),如果不實現(xiàn),網(wǎng)頁的alert函數(shù)無效
    UIAlertController *alertController = [UIAlertController alertControllerWithTitle:message message:nil preferredStyle:UIAlertControllerStyleAlert];
    [alertController addAction:[UIAlertAction actionWithTitle:@"確定" style:UIAlertActionStyleCancel handler:^(UIAlertAction * _Nonnull action) {
        completionHandler();
    }]];
    [self presentViewController:alertController animated:YES completion:^{}];
}

白屏問題

當(dāng)WKWebView加載的網(wǎng)頁占用內(nèi)存過大時,會出現(xiàn)白屏現(xiàn)象。解決方案是

- (void)webViewWebContentProcessDidTerminate:(WKWebView *)webView {
    [webView reload];   //刷新就好了
}

有時白屏,不會調(diào)用該方法,具體的解決方案是

比如,最近遇到在一個高內(nèi)存消耗的H5頁面上 present 系統(tǒng)相機,拍照完畢后返回原來頁面的時候出現(xiàn)白屏現(xiàn)象(拍照過程消耗了大量內(nèi)存,導(dǎo)致內(nèi)存緊張,WebContent Process 被系統(tǒng)掛起),但上面的回調(diào)函數(shù)并沒有被調(diào)用。在WKWebView白屏的時候,另一種現(xiàn)象是 webView.titile 會被置空, 因此,可以在 viewWillAppear 的時候檢測 webView.title 是否為空來 reload 頁面。(出自WKWebView 那些坑

自定義contentInset刷新時頁面跳動的bug
self.webView.scrollView.contentInset = UIEdgeInsetsMake(64, 0, 49, 0);
//史詩級神坑,為何如此寫呢?參考https://opensource.apple.com/source/WebKit2/WebKit2-7600.1.4.11.10/ChangeLog  
[self.webView setValue:[NSValue valueWithUIEdgeInsets:self.webView.scrollView.contentInset] forKey:@"_obscuredInsets"]; //kvc給WKWebView的私有變量_obscuredInsets設(shè)置值
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容