14-3 iOS 與H5

執(zhí)行一段js代碼

#pragma mark --  收集JS頁面?zhèn)鱽淼膱D片及添加圖片點擊事件
-(void)getImagesFromJSAndClickImgEvent:(WKWebView *)webView{
    //這里是JS峰搪,主要目的: - 獲取H5圖片的url
    static  NSString * const jsGetImages =
    @"function getImages(){\
    var objs = document.getElementsByTagName(\"img\");\
    var imgScr = '';\
    for(var i=0;i<objs.length;i++){\
    imgScr = imgScr + objs[i].src + '+';\
    };\
    return imgScr;\
    };";
    WS(weakSelf);
    [self.webView evaluateJavaScript:jsGetImages completionHandler:^(id _Nullable result, NSError * _Nullable error) {
        
    }];
    
    [self.webView evaluateJavaScript:@"getImages()" completionHandler:^(id _Nullable result, NSError * _Nullable error) {
        SS(strongSelf);
        strongSelf.mUrlArray = [NSMutableArray arrayWithArray:[result componentsSeparatedByString:@"+"]];
        if (strongSelf.mUrlArray.count >= 2) {
            [strongSelf.mUrlArray removeLastObject];
        }
    }];
    
    [self.webView evaluateJavaScript:@"function registerImageClickAction(){\
     var imgs=document.getElementsByTagName('img');\
     var length=imgs.length;\
     for(var i=0;i<length;i++){\
     img=imgs[i];\
     img.onclick=function(){\
     window.location.href='image-preview:'+this.src}\
     }\
     }" completionHandler:^(id _Nullable result, NSError * _Nullable error) {
        
    }];
    
    [self.webView evaluateJavaScript:@"registerImageClickAction();" completionHandler:^(id _Nullable result, NSError * _Nullable error) {
        
    }];
    
}

計算高度:
    //加載web頁面數據
    NSString *fullContent = @"<html><head><meta name=\"viewport\" content=\"width=device-width, initial-scale=1,maximum-scale=1, user-scalable=no\" /><link href=\"http://apps.bdimg.com/libs/bootstrap/3.3.4/css/bootstrap.css\" rel=\"stylesheet\"></head><body><div style=\"font-size:14px;width:100%;line-height:1.6;word-break;break-all;word-wrap:break-word;padding-bottom:20px;color: #999999;\">'+temp+'</div><div id=\"testDiv\" style = \"height:0; width:100px\"></div></body></html>";
    //防止/n不換行遗嗽,替換標簽
    NSString *changeContent = [model.content stringByReplacingOccurrencesOfString:@"\n" withString:@"<br>"];
    fullContent = [fullContent stringByReplacingOccurrencesOfString:@"'+temp+'" withString:STRING_NIL(changeContent)];
    fullContent = [fullContent stringByReplacingOccurrencesOfString:@"<b>" withString:@"<b style=\"color: #333333; font-size: 16px;\">"];
    fullContent = [fullContent stringByReplacingOccurrencesOfString:@"display:block;width:100%" withString:[NSString stringWithFormat:@"display:block;width:%fpx",Screen_W - 40]];
    
    [self.webView loadHTMLString:fullContent baseURL:nil];
   
    
    WS(weakSelf);
    [self.webView evaluateJavaScript:@"document.getElementById(\"testDiv\").offsetTop" completionHandler:^(id _Nullable result, NSError * _Nullable error) {
        SS(strongSelf);
        //獲取頁面高度创译,并重置webview的frame
        strongSelf.model.height = [result doubleValue] + 84;
    }];

2.注入監(jiān)聽方法不是方法

    // WKWebView的配置
    WKWebViewConfiguration *configuration = [[WKWebViewConfiguration alloc] init];
    [configuration.userContentController addScriptMessageHandler:self name:@"userSelectionString"];
    // js 方法注入
    NSString *printContent = @"document.addEventListener('selectionchange', function () {window.webkit.messageHandlers.userSelectionString.postMessage(window.getSelection().toString());})";
    WKUserScript *userScript = [[WKUserScript alloc] initWithSource:printContent injectionTime:WKUserScriptInjectionTimeAtDocumentEnd forMainFrameOnly:YES];
    [configuration.userContentController addUserScript:userScript];

- (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message {
    NSLog(@"userContentController %@",message.body);
    NSLog(@"userContentController %@",message.name);
}

3.獲取文字

    NSString *lJs2 = @"document.documentElement.innerText"; //根據標識符獲取不同內容

4.獲取WebView加載的HTML

[webView evaluateJavaScript:@"document.getElementsByTagName('html')[0].innerHTML" completionHandler:^(id result, NSError * _Nullable error) {
    NSString *html = result;
    NSLog(@"%@", html);
}];

5.JS調用iOS的代碼

    WKWebViewConfiguration *configuration = [[WKWebViewConfiguration alloc] init];
    [configuration.userContentController addScriptMessageHandler:self name:@"userSelectionString"];

- (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message {

    NSString *body = message.body;
    if ([NSString isBlankString:body]) {
        
    } else {
        
    }
}

js方法:window.webkit.messageHandlers.userSelectionString.postMessage(window.getSelection().toString())
最好是傳json

5.wkwebview 去掉剪切板

#import "HDPlayBackMuluWebView.h"

BOOL wel_canPerformAction(id self,  SEL _cmd, SEL arg1, id arg2) {
    return NO;
}


@implementation HDPlayBackMuluWebView


/// iOS 10.0 調用
+ (void)load {
    
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        Method  m = class_getInstanceMethod(NSClassFromString(@"WKContentView"), NSSelectorFromString(@"canPerformAction:withSender:"));
        
        class_addMethod(NSClassFromString(@"WKContentView"), NSSelectorFromString(@"wel_canPerformAction:withSender:"), (IMP)wel_canPerformAction, method_getTypeEncoding(m));
        
        Method m1 = class_getInstanceMethod(NSClassFromString(@"WKContentView"), NSSelectorFromString(@"canPerformAction:withSender:"));
        Method m2 = class_getInstanceMethod(NSClassFromString(@"WKContentView"), NSSelectorFromString(@"wel_canPerformAction:withSender:"));
        method_exchangeImplementations(m1,m2);
    });
}

- (BOOL)wel_canPerformAction:(SEL)arg1 withSender:(id)arg2 {
    return NO;
}


/// iOS 10.0 的系統(tǒng)不可以用
- (BOOL)canPerformAction:(SEL)action withSender:(id)sender {
    return NO;
}
@end

6優(yōu)化工作

1.白屏
2.cookie
3.秒開:緩存和預加載

1.使用本地資源 文件

1.這邊實現(xiàn)了一個 webview 緩沖池的方案穿稳,在 App 啟動的時候就初始化了,在需要打開網頁的時候直接從緩沖池里面去取 webview 就行
2.自定義攔截請求 setURLSchemeHandler 把能緩存的都緩存[html 攔截/js || css 文件/]下來 并且可以設置緩存的策略 內存緩存 和 硬盤緩存. 使用請求頭獲取到請求的資源:Accept
3.在 webview 初始化的同時并行去請求數據?這個怎么做 使用js和H5的交互

2.使用緩存

1.頁面即將白屏的時候WKNavigationDelegate會回調一個方法 我們在這里執(zhí)行reload方法
2.在跳轉其他頁面占有大量內存的時候卷玉。在viewwillapple執(zhí)行reload方法

3.cookie問題 服務器返回給iOS iOS請求在帶給服務器 或者H5 Cookie最常用的也就是維持登錄狀態(tài)了

cookie 我們登陸成功后獲取到cookie。然后首次打開 webview的時候攜帶上
存儲的時候我們需要區(qū)分iOS11 和 iOS 11 之前

iOS11之前
1.iOS和js交互 通過 document.cookie 設置 Cookie 解決后續(xù)頁面(同域)Ajax喷市、iframe 請求的 Cookie 問題
2.拼接在header里面 設置請求頭  不能被js讀取到
通過key-Value構造一個cookie相种,WKWebView loadRequest 前,在 request header 中設置 Cookie, 解決首個請求 Cookie 帶不上的問題品姓,

iOS11之后 將cookie存入到WKHTTPCookieStore里面
    /// 發(fā)送請求之前
    if (@available(iOS 11.0, *)) {
        WKHTTPCookieStore *httpCookieStore = webView.configuration.websiteDataStore.httpCookieStore;
        for (NSHTTPCookie *cookie in cookies) {
            [httpCookieStore setCookie:cookie completionHandler:^{
                            
            }];
        }
    } else {
        // Fallback on earlier versions
    }

獲取cookie是從登陸成功的接口中獲取的寝并,這個時候的cookie是被同步到了[[NSHTTPCookieStorage sharedHTTPCookieStorage] cookies]中,其實整個app的生命周期里缭黔,所有的通過網絡請求用到的cookie都會被同步到這個單例中食茎,由它進行管理。
然后保存起來 


獲取cookie 存起來:1)從網站返回的 response headerfields 中獲取馏谨。(2)通過調用js的方法獲取 cookie别渔。
- (void)webView:(WKWebView *)webView decidePolicyForNavigationResponse:(WKNavigationResponse *)navigationResponse decisionHandler:(void (^)(WKNavigationResponsePolicy))decisionHandler{
    NSHTTPURLResponse *response = (NSHTTPURLResponse *)navigationResponse.response;
    NSArray *cookies =[NSHTTPCookie cookiesWithResponseHeaderFields:[response allHeaderFields] forURL:response.URL];
    NSLog(@"\n====================================\n");
    //讀取wkwebview中的cookie 方法1
    for (NSHTTPCookie *cookie in cookies) {
        //        [[NSHTTPCookieStorage sharedHTTPCookieStorage] setCookie:cookie];
        NSLog(@"wkwebview中的cookie:%@", cookie);
    }
    NSLog(@"\n====================================\n");
    //讀取wkwebview中的cookie 方法2 讀取Set-Cookie字段
    NSString *cookieString = [[response allHeaderFields] valueForKey:@"Set-Cookie"];
    NSLog(@"wkwebview中的cookie:%@", cookieString);
    NSLog(@"\n====================================\n");
    //看看存入到了NSHTTPCookieStorage了沒有
    NSHTTPCookieStorage *cookieJar2 = [NSHTTPCookieStorage sharedHTTPCookieStorage];
    for (NSHTTPCookie *cookie in cookieJar2.cookies) {
        NSLog(@"NSHTTPCookieStorage中的cookie%@", cookie);
    }
    NSLog(@"\n====================================\n");

    decisionHandler(WKNavigationResponsePolicyAllow);
}

通過 JS 獲取 cookie
- (void)webView:(WKWebView *)webView didFinishNavigation:(null_unspecified WKNavigation *)navigation
{
    
    [webView evaluateJavaScript:[NSString stringWithFormat:@"document.cookie"] completionHandler:^(id _Nullable response, NSError * _Nullable error) {
        if (response != 0) {
            NSLog(@"\n\n\n\n\n\n document.cookie%@,%@",response,error);
        }
    }];
}


document.cookie 的方法獲取 cookie并不支持跨越獲取
1.加載一個本地為空的html,域名指向你的第一次加載的url的域名惧互。
    if ([response.URL.scheme.lowercaseString containsString:@"http"]) {
        NSArray *cookies =[NSHTTPCookie cookiesWithResponseHeaderFields:[response allHeaderFields] forURL:response.URL];
        if (@available(iOS 11.0, *)) {
            //瀏覽器自動存儲cookie
        }else
        {
            //存儲cookies
            dispatch_sync(dispatch_get_global_queue(0, 0), ^{
                
                @try{
                    //存儲cookies
                    for (NSHTTPCookie *cookie in cookies) {
                        [weakSelf.webView insertCookie:cookie];
                    }
                }@catch (NSException *e) {
                    NSLog(@"failed: %@", e);
                } @finally {
                    
                }
            });
        }
        
    }

性能優(yōu)化 我們本地加載數據 + 加載web頁面哎媚。然后數據展示:
NB啊這個人

iOS 端 h5 頁面秒開優(yōu)化實踐

http://www.reibang.com/p/cd0d819b9851

iOS UIWebView 和 WKWebView 的 cookie 獲取,設置,刪除
這里討論了 H5 頁面首屏啟動時間的優(yōu)化,上述優(yōu)化過后喊儡,基本上耗時只剩 webview 本身的啟動/渲染機制問題了拨与,這個問題跟后續(xù)的響應流暢度的問題一起屬于另一個優(yōu)化范圍,就是類 RN / Weex 這樣的方案艾猜,有機會再探討买喧。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末捻悯,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子淤毛,更是在濱河造成了極大的恐慌今缚,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,948評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件低淡,死亡現(xiàn)場離奇詭異姓言,居然都是意外死亡,警方通過查閱死者的電腦和手機蔗蹋,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,371評論 3 385
  • 文/潘曉璐 我一進店門何荚,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人猪杭,你說我怎么就攤上這事餐塘。” “怎么了胁孙?”我有些...
    開封第一講書人閱讀 157,490評論 0 348
  • 文/不壞的土叔 我叫張陵唠倦,是天一觀的道長。 經常有香客問我涮较,道長,這世上最難降的妖魔是什么冈止? 我笑而不...
    開封第一講書人閱讀 56,521評論 1 284
  • 正文 為了忘掉前任,我火速辦了婚禮熙暴,結果婚禮上闺属,老公的妹妹穿的比我還像新娘。我一直安慰自己周霉,他們只是感情好掂器,可當我...
    茶點故事閱讀 65,627評論 6 386
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著俱箱,像睡著了一般国瓮。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上狞谱,一...
    開封第一講書人閱讀 49,842評論 1 290
  • 那天乃摹,我揣著相機與錄音,去河邊找鬼跟衅。 笑死孵睬,一個胖子當著我的面吹牛,可吹牛的內容都是我干的伶跷。 我是一名探鬼主播掰读,決...
    沈念sama閱讀 38,997評論 3 408
  • 文/蒼蘭香墨 我猛地睜開眼秘狞,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了蹈集?” 一聲冷哼從身側響起烁试,我...
    開封第一講書人閱讀 37,741評論 0 268
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎雾狈,沒想到半個月后廓潜,有當地人在樹林里發(fā)現(xiàn)了一具尸體,經...
    沈念sama閱讀 44,203評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡善榛,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 36,534評論 2 327
  • 正文 我和宋清朗相戀三年辩蛋,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片移盆。...
    茶點故事閱讀 38,673評論 1 341
  • 序言:一個原本活蹦亂跳的男人離奇死亡悼院,死狀恐怖,靈堂內的尸體忽然破棺而出咒循,到底是詐尸還是另有隱情据途,我是刑警寧澤,帶...
    沈念sama閱讀 34,339評論 4 330
  • 正文 年R本政府宣布叙甸,位于F島的核電站颖医,受9級特大地震影響,放射性物質發(fā)生泄漏裆蒸。R本人自食惡果不足惜熔萧,卻給世界環(huán)境...
    茶點故事閱讀 39,955評論 3 313
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望僚祷。 院中可真熱鬧佛致,春花似錦、人聲如沸辙谜。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,770評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽装哆。三九已至罐脊,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間烂琴,已是汗流浹背爹殊。 一陣腳步聲響...
    開封第一講書人閱讀 32,000評論 1 266
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留奸绷,地道東北人梗夸。 一個月前我還...
    沈念sama閱讀 46,394評論 2 360
  • 正文 我出身青樓,卻偏偏與公主長得像号醉,于是被迫代替她去往敵國和親反症。 傳聞我的和親對象是個殘疾皇子辛块,可洞房花燭夜當晚...
    茶點故事閱讀 43,562評論 2 349

推薦閱讀更多精彩內容