iOS - UIWebView和WKWebView的比較和選擇-做爲H5容器的一些探究

1、Native開發中爲何須要H5容器javascript

Native開發原生應用是手機操做系統廠商(目前主要是蘋果的iOS和google的Android)對外界提供的標準化的開發模式,他們對於native開發提供了一套標準化實現和優化方案。可是他們存在一些硬傷,好比App的發版週期偏長、有時沒法跟上產品的更新節奏;靈活性差,若是有較大的方案變動,須要發版才能解決;若是存在bug,在當前版本修復的難度比較大(iOS的JSPatch方案和Android的Dex修復方案);須要根據不一樣的平臺寫不一樣的代碼,iOS主要爲object_c和swift,android爲Java。css

而做爲H5爲主要開發模式的Web App的靈活性就比較強,他利用操做系統中的h5容器做爲一個承載,對外提供一個url連接,而該url連接對應的內容能夠實時在服務端進行修改,靈活行很強,避免了Native發版週期帶來的時間成本。可是h5雖然靈活,可是他也有本身的硬傷。每次都須要下載完整的UI數據(html,css,js),弱網用戶體驗較差,流量消耗較大;沒法調用系統文件系統,硬件資源等等;html

Native App和Web App都有他們的優點和劣勢。咱們也不能一棍子拍死說誰好誰劣。一般的經驗是:對於一些比較妥當的業務,對用戶體驗要求較高的,咱們能夠選擇Native開發。而對於一些業務變動比較快、處在不斷試水的過程,並且不涉及調用文件系統和硬件調用的業務咱們能夠選擇h5開發。因此說,在一款app中咱們須要同時支持Native代碼和h5代碼。這也是咱們標題所說的Native開發中須要H5容器的必要性。java

iOS存在的h5容器主要包括UIWebView和WKWebView,下面咱們就分別來講說他們的用法和優劣。android

2、UIWebView的基本用法ios

2.一、加載網頁web

 

Crayon Syntax Highlighter v2.7.1.1swift

 

 

 

 

 

 

 

Objective-C緩存

 UIWebView *webView = [[UIWebView alloc] initWithFrame:self.view.bounds];服務器

    webView.delegate = self;

    [self.view addSubview:webView];

    //網絡地址

    NSURL *url = [[NSURL alloc] initWithString:@"http://www.taobao.com"];

    NSURLRequest *request = [NSURLRequest requestWithURL:url];

    [webView loadRequest:request];

1

2

3

4

5

6

7

 UIWebView *webView = [[UIWebView alloc] initWithFrame:self.view.bounds];

    webView.delegate = self;

    [self.view addSubview:webView];

    //網絡地址

    NSURL *url = [[NSURL alloc] initWithString:@"http://www.taobao.com"];

    NSURLRequest *request = [NSURLRequest requestWithURL:url];

    [webView loadRequest:request];

[Format Time: 0.0018 seconds]

 

2.二、UIWebViewDelegate幾個經常使用的代理方法

 

Crayon Syntax Highlighter v2.7.1.1

 

 

 

 

 

 

 

Objective-C

//進行加載前的預判斷,若是返回YES,則會進入後續流程(StartLoad,FinishLoad)。若是返回NO,這不會進入後續流程。

- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType;

//開始加載網頁

- (void)webViewDidStartLoad:(UIWebView *)webView;

//加載完成

- (void)webViewDidFinishLoad:(UIWebView *)webView;

//加載失敗

- (void)webView:(UIWebView *)webView didFailLoadWithError:(nullable NSError *)error;

1

2

3

4

5

6

7

8

//進行加載前的預判斷,若是返回YES,則會進入後續流程(StartLoad,FinishLoad)。若是返回NO,這不會進入後續流程。

- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType;

//開始加載網頁

- (void)webViewDidStartLoad:(UIWebView *)webView;

//加載完成

- (void)webViewDidFinishLoad:(UIWebView *)webView;

//加載失敗

- (void)webView:(UIWebView *)webView didFailLoadWithError:(nullable NSError *)error;

[Format Time: 0.0019 seconds]

 

2.三、Native調用JS中的方法

好比咱們在加載的HTML文件中有以下js代碼:

Crayon Syntax Highlighter v2.7.1.1

 

 

 

 

 

 

JavaScript

<script type="text/javascript">

function hello(){

    alert("你好!");

}

 

function helloWithName(name){

    alert(name + ",你好!");

}

</script>

1

2

3

4

5

6

7

8

9

<script type="text/javascript">

function hello(){

    alert("你好!");

}

 

function helloWithName(name){

    alert(name + ",你好!");

}

</script>

[Format Time: 0.0011 seconds]

咱們能夠調用- (nullable NSString )stringByEvaluatingJavaScriptFromString:(NSString )script;函數進行js調用。

Crayon Syntax Highlighter v2.7.1.1

 

 

 

 

 

 

Objective-C

[webView stringByEvaluatingJavaScriptFromString:@"hello()"];

[webView stringByEvaluatingJavaScriptFromString:@"helloWithName('jack')"];

1

2

[webView stringByEvaluatingJavaScriptFromString:@"hello()"];

[webView stringByEvaluatingJavaScriptFromString:@"helloWithName('jack')"];

[Format Time: 0.0006 seconds]

js代碼不必定要在js文件中預留,也能夠在代碼中經過字符串的形式進行調用,好比下面:

Crayon Syntax Highlighter v2.7.1.1

 

 

 

 

 

 

Objective-C

   //自定義js函數

    NSString *jsString = @"function sayHello(){ \

                                alert('jack11')   \

                            }                   \

                           sayHello()";

    [_webView stringByEvaluatingJavaScriptFromString:jsString];

 

    NSString *jsString = @" var p = document.createElement('p'); \

                            p.innerText = 'New Line';            \

                            document.body.appendChild(p);        \

    ";

    [_webView stringByEvaluatingJavaScriptFromString:jsString];

1

2

3

4

5

6

7

8

9

10

11

12

   //自定義js函數

    NSString *jsString = @"function sayHello(){ \

                                alert('jack11')   \

                            }                   \

                           sayHello()";

    [_webView stringByEvaluatingJavaScriptFromString:jsString];

 

    NSString *jsString = @" var p = document.createElement('p'); \

                            p.innerText = 'New Line';            \

                            document.body.appendChild(p);        \

    ";

    [_webView stringByEvaluatingJavaScriptFromString:jsString];

[Format Time: 0.0012 seconds]

 

2.四、JS中調用Naitve的方法

具體讓js通知native進行方法調用,咱們可讓js產生一個特殊的請求。可讓Native代碼能夠攔截到,並且否則用戶察覺。業界通常的實現方案是在網頁中加載一個隱藏的iframe來實現該功能。經過將iframe的src指定爲一個特殊的URL,實如今- (BOOL)webView:(UIWebView )webView shouldStartLoadWithRequest:(NSURLRequest )request navigationType:(UIWebViewNavigationType)navigationType;方案中進行攔截處理。對應的js調用代碼以下:

Crayon Syntax Highlighter v2.7.1.1

 

 

 

 

 

 

JavaScript

 function loadURL(url) {

        var iFrame;

        iFrame = document.createElement("iframe");

        iFrame.setAttribute("src", url);

        iFrame.setAttribute("style", "display:none;");

        iFrame.setAttribute("height", "0px");

        iFrame.setAttribute("width", "0px");

        iFrame.setAttribute("frameborder", "0");

        document.body.appendChild(iFrame);

        // 發起請求後這個iFrame就沒用了,因此把它從dom上移除掉

        iFrame.parentNode.removeChild(iFrame);

        iFrame = null;

    }

1

2

3

4

5

6

7

8

9

10

11

12

13

 function loadURL(url) {

        var iFrame;

        iFrame = document.createElement("iframe");

        iFrame.setAttribute("src", url);

        iFrame.setAttribute("style", "display:none;");

        iFrame.setAttribute("height", "0px");

        iFrame.setAttribute("width", "0px");

        iFrame.setAttribute("frameborder", "0");

        document.body.appendChild(iFrame);

        // 發起請求後這個iFrame就沒用了,因此把它從dom上移除掉

        iFrame.parentNode.removeChild(iFrame);

        iFrame = null;

    }

[Format Time: 0.0025 seconds]

好比咱們在js代碼中,調用一下兩個js方法:

Crayon Syntax Highlighter v2.7.1.1

 

 

 

 

 

 

JavaScript

function iOS_alert() {//調用自定義對話框

        loadURL("alert://abc");

    }

    function call() {//  js中進行撥打電話處理

        loadURL("tel://17715022071");

    }

1

2

3

4

5

6

function iOS_alert() {//調用自定義對話框

        loadURL("alert://abc");

    }

    function call() {//  js中進行撥打電話處理

        loadURL("tel://17715022071");

    }

[Format Time: 0.0009 seconds]

當你觸發以上方法的時候,就會進入webview的代理方法中進行攔截。

Crayon Syntax Highlighter v2.7.1.1

 

 

 

 

 

 

 

Objective-C

- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType{

    NSURL * url = [request URL];

    if ([[url scheme] isEqualToString:@"alert"]) {//攔截請求,彈出自定義對話框

        UIAlertView * alertView = [[UIAlertView alloc] initWithTitle:@"test" message:[url host] delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil];

        [alertView show];

        return NO;

    }else if([[url scheme] isEqualToString:@"tel"]){//攔截撥打電話請求

        BOOL result = [[UIApplication sharedApplication] openURL:url];

        if (!result) {

            NSLog(@"您的設備不支持打電話");

        } else {

            NSLog(@"電話打了");

        }

        return NO;

    }

 

    return YES;

}

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType{

    NSURL * url = [request URL];

    if ([[url scheme] isEqualToString:@"alert"]) {//攔截請求,彈出自定義對話框

        UIAlertView * alertView = [[UIAlertView alloc] initWithTitle:@"test" message:[url host] delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil];

        [alertView show];

        return NO;

    }else if([[url scheme] isEqualToString:@"tel"]){//攔截撥打電話請求

        BOOL result = [[UIApplication sharedApplication] openURL:url];

        if (!result) {

            NSLog(@"您的設備不支持打電話");

        } else {

            NSLog(@"電話打了");

        }

        return NO;

    }

 

    return YES;

}

[Format Time: 0.0039 seconds]

這樣咱們就可讓js進行native的調用。

3、WKWebView的基本用法

3.一、加載網頁

 

Crayon Syntax Highlighter v2.7.1.1

 

 

 

 

 

 

 

Objective-C

  WKWebView *webView = [[WKWebView alloc] initWithFrame:[UIScreen mainScreen].bounds];

    NSURL *url = [NSURL URLWithString:@"http://www.taobao.com"];

    NSURLRequest *request = [NSURLRequest requestWithURL:url];

    [webView loadRequest:request];

    [self.view addSubview:webView];

1

2

3

4

5

  WKWebView *webView = [[WKWebView alloc] initWithFrame:[UIScreen mainScreen].bounds];

    NSURL *url = [NSURL URLWithString:@"http://www.taobao.com"];

    NSURLRequest *request = [NSURLRequest requestWithURL:url];

    [webView loadRequest:request];

    [self.view addSubview:webView];

[Format Time: 0.0017 seconds]

 

3.二、幾個經常使用的代理方法

 

Crayon Syntax Highlighter v2.7.1.1

 

 

 

 

 

 

 

Objective-C

/**

 *  根據webView、navigationAction相關信息決定此次跳轉是否能夠繼續進行,這些信息包含HTTP發送請求,如頭部包含User-Agent,Accept,refer

 *  在發送請求以前,決定是否跳轉的代理

 *  @param webView

 *  @param navigationAction

 *  @param decisionHandler

 */

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

    decisionHandler(WKNavigationActionPolicyAllow);

}

 

/**

 *  這個代理方法表示當客戶端收到服務器的響應頭,根據response相關信息,能夠決定此次跳轉是否能夠繼續進行。

 *  在收到響應後,決定是否跳轉的代理

 *  @param webView

 *  @param navigationResponse

 *  @param decisionHandler

 */

- (void)webView:(WKWebView *)webView decidePolicyForNavigationResponse:(WKNavigationResponse *)navigationResponse decisionHandler:(void (^)(WKNavigationResponsePolicy))decisionHandler{

    decisionHandler(WKNavigationResponsePolicyAllow);

}

 

/**

 *  準備加載頁面。等同於UIWebViewDelegate: - webView:shouldStartLoadWithRequest:navigationType

 *

 *  @param webView

 *  @param navigation

 */

- (void)webView:(WKWebView *)webView didStartProvisionalNavigation:(null_unspecified WKNavigation *)navigation{

}

 

/**

 *  這個代理是服務器redirect時調用

 *  接收到服務器跳轉請求的代理

 *  @param webView

 *  @param navigation

 */

- (void)webView:(WKWebView *)webView didReceiveServerRedirectForProvisionalNavigation:(null_unspecified WKNavigation *)navigation{

 

}

 

- (void)webView:(WKWebView *)webView didFailProvisionalNavigation:(null_unspecified WKNavigation *)navigation withError:(NSError *)error{

 

}

 

/**

 *  內容開始加載. 等同於UIWebViewDelegate: - webViewDidStartLoad:

 *

 *  @param webView

 *  @param navigation

 */

- (void)webView:(WKWebView *)webView didCommitNavigation:(null_unspecified WKNavigation *)navigation{

 

}

 

/**

 *  頁面加載完成。 等同於UIWebViewDelegate: - webViewDidFinishLoad:

 *

 *  @param webView

 *  @param navigation

 */

- (void)webView:(WKWebView *)webView didFinishNavigation:(null_unspecified WKNavigation *)navigation{

 

}

 

/**

 *  頁面加載失敗。 等同於UIWebViewDelegate: - webView:didFailLoadWithError:

 *

 *  @param webView

 *  @param navigation

 *  @param error      

 */

- (void)webView:(WKWebView *)webView didFailNavigation:(null_unspecified WKNavigation *)navigation withError:(NSError *)error{

 

}

 

- (void)webViewWebContentProcessDidTerminate:(WKWebView *)webView NS_AVAILABLE(10_11, 9_0){

 

}

 

/*

 咱們看看WKUIDelegate的幾個代理方法,雖然不是必須實現的,可是若是咱們的頁面中有調用了js的alert、confirm、prompt方法,咱們應該實現下面這幾個代理方法,而後在原來這裏調用native的彈出窗,由於使用WKWebView後,HTML中的alert、confirm、prompt方法調用是不會再彈出窗口了,只是轉化成ios的native回調代理方法

 */

#pragma mark - WKUIDelegate

 

- (void)webView:(WKWebView *)webView runJavaScriptAlertPanelWithMessage:(NSString *)message initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(void))completionHandler{

    UIAlertController *alertView = [UIAlertController alertControllerWithTitle:@"h5Container" message:message preferredStyle:UIAlertControllerStyleAlert];

//    [alertView addTextFieldWithConfigurationHandler:^(UITextField * _Nonnull textField) {

//        textField.textColor = [UIColor redColor];

//    }];

    [alertView addAction:[UIAlertAction actionWithTitle:@"我很肯定" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {

        completionHandler();

    }]];

    [self presentViewController:alertView animated:YES completion:nil];

}

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

/**

 *  根據webView、navigationAction相關信息決定此次跳轉是否能夠繼續進行,這些信息包含HTTP發送請求,如頭部包含User-Agent,Accept,refer

 *  在發送請求以前,決定是否跳轉的代理

 *  @param webView

 *  @param navigationAction

 *  @param decisionHandler

 */

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

    decisionHandler(WKNavigationActionPolicyAllow);

}

 

/**

 *  這個代理方法表示當客戶端收到服務器的響應頭,根據response相關信息,能夠決定此次跳轉是否能夠繼續進行。

 *  在收到響應後,決定是否跳轉的代理

 *  @param webView

 *  @param navigationResponse

 *  @param decisionHandler

 */

- (void)webView:(WKWebView *)webView decidePolicyForNavigationResponse:(WKNavigationResponse *)navigationResponse decisionHandler:(void (^)(WKNavigationResponsePolicy))decisionHandler{

    decisionHandler(WKNavigationResponsePolicyAllow);

}

 

/**

 *  準備加載頁面。等同於UIWebViewDelegate: - webView:shouldStartLoadWithRequest:navigationType

 *

 *  @param webView

 *  @param navigation

 */

- (void)webView:(WKWebView *)webView didStartProvisionalNavigation:(null_unspecified WKNavigation *)navigation{

}

 

/**

 *  這個代理是服務器redirect時調用

 *  接收到服務器跳轉請求的代理

 *  @param webView

 *  @param navigation

 */

- (void)webView:(WKWebView *)webView didReceiveServerRedirectForProvisionalNavigation:(null_unspecified WKNavigation *)navigation{

 

}

 

- (void)webView:(WKWebView *)webView didFailProvisionalNavigation:(null_unspecified WKNavigation *)navigation withError:(NSError *)error{

 

}

 

/**

 *  內容開始加載. 等同於UIWebViewDelegate: - webViewDidStartLoad:

 *

 *  @param webView

 *  @param navigation

 */

- (void)webView:(WKWebView *)webView didCommitNavigation:(null_unspecified WKNavigation *)navigation{

 

}

 

/**

 *  頁面加載完成。 等同於UIWebViewDelegate: - webViewDidFinishLoad:

 *

 *  @param webView

 *  @param navigation

 */

- (void)webView:(WKWebView *)webView didFinishNavigation:(null_unspecified WKNavigation *)navigation{

 

}

 

/**

 *  頁面加載失敗。 等同於UIWebViewDelegate: - webView:didFailLoadWithError:

 *

 *  @param webView

 *  @param navigation

 *  @param error      

 */

- (void)webView:(WKWebView *)webView didFailNavigation:(null_unspecified WKNavigation *)navigation withError:(NSError *)error{

 

}

 

- (void)webViewWebContentProcessDidTerminate:(WKWebView *)webView NS_AVAILABLE(10_11, 9_0){

 

}

 

/*

 咱們看看WKUIDelegate的幾個代理方法,雖然不是必須實現的,可是若是咱們的頁面中有調用了js的alert、confirm、prompt方法,咱們應該實現下面這幾個代理方法,而後在原來這裏調用native的彈出窗,由於使用WKWebView後,HTML中的alert、confirm、prompt方法調用是不會再彈出窗口了,只是轉化成ios的native回調代理方法

 */

#pragma mark - WKUIDelegate

 

- (void)webView:(WKWebView *)webView runJavaScriptAlertPanelWithMessage:(NSString *)message initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(void))completionHandler{

    UIAlertController *alertView = [UIAlertController alertControllerWithTitle:@"h5Container" message:message preferredStyle:UIAlertControllerStyleAlert];

//    [alertView addTextFieldWithConfigurationHandler:^(UITextField * _Nonnull textField) {

//        textField.textColor = [UIColor redColor];

//    }];

    [alertView addAction:[UIAlertAction actionWithTitle:@"我很肯定" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {

        completionHandler();

    }]];

    [self presentViewController:alertView animated:YES completion:nil];

}

[Format Time: 0.0084 seconds]

顯然WKWebView的代理方法提供了比UIWebView顆粒度更細的方法。讓開發者能夠進行更加細緻的配置和處理。

3.3 、Native調用JS中的方法

WKWebView提供的調用js代碼的函數是:

Crayon Syntax Highlighter v2.7.1.1

 

 

 

 

 

 

 

Objective-C

- (void)evaluateJavaScript:(NSString *)javaScriptString completionHandler:(void (^ __nullable)(__nullable id, NSError * __nullable error))completionHandler;

1

- (void)evaluateJavaScript:(NSString *)javaScriptString completionHandler:(void (^ __nullable)(__nullable id, NSError * __nullable error))completionHandler;

[Format Time: 0.0010 seconds]

好比咱們在加載的HTML文件中有以下js代碼:

Crayon Syntax Highlighter v2.7.1.1

 

 

 

 

 

 

JavaScript

<script type="text/javascript">

function hello(){

    alert("你好!");

}

 

function helloWithName(name){

    alert(name + ",你好!");

}

</script>

1

2

3

4

5

6

7

8

9

<script type="text/javascript">

function hello(){

    alert("你好!");

}

 

function helloWithName(name){

    alert(name + ",你好!");

}

</script>

[Format Time: 0.0012 seconds]

咱們能夠調用以下代碼進行js的調用:

Crayon Syntax Highlighter v2.7.1.1

  

Objective-C

[_wkView evaluateJavaScript:@"hello()" completionHandler:^(id item, NSError * error) {

 

}];

 

 [_wkView evaluateJavaScript:@"helloWithName('jack')" completionHandler:^(id item, NSError *error) {

 

}];

1

2

3

4

5

6

7

[_wkView evaluateJavaScript:@"hello()" completionHandler:^(id item, NSError * error) {

 

}];

 

 [_wkView evaluateJavaScript:@"helloWithName('jack')" completionHandler:^(id item, NSError *error) {

 

}];

[Format Time: 0.0012 seconds]

同UIWebView同樣,咱們也能夠經過字符串的形式進行js調用。

Crayon Syntax Highlighter v2.7.1.1

 

 

Objective-C

 NSString *jsString = @"function sayHello(){ \

                                    alert('jack11')   \

                                }                   \

                               sayHello()";

    [_wkView evaluateJavaScript:jsString completionHandler:^(id item, NSError *error) {

 

    }];

 

    jsString = @" var p = document.createElement('p'); \

    p.innerText = 'New Line';            \

    document.body.appendChild(p);        \

    ";

    [_wkView evaluateJavaScript:jsString completionHandler:^(id item, NSError *error) {

 

    }];

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

 NSString *jsString = @"function sayHello(){ \

                                    alert('jack11')   \

                                }                   \

                               sayHello()";

    [_wkView evaluateJavaScript:jsString completionHandler:^(id item, NSError *error) {

 

    }];

 

    jsString = @" var p = document.createElement('p'); \

    p.innerText = 'New Line';            \

    document.body.appendChild(p);        \

    ";

    [_wkView evaluateJavaScript:jsString completionHandler:^(id item, NSError *error) {

 

    }];

[Format Time: 0.0019 seconds]

 

3.四、JS中調用Naitve的方法

除了和UIWebView加載一個隱藏的ifame以外,WKWebView自身還提供了一套js調用native的規範。

咱們能夠在初始化WKWebView的時候,給他設置一個config參數。

Crayon Syntax Highlighter v2.7.1.1

 

 

Objective-C

//高端配置

    //建立配置

    WKWebViewConfiguration *config = [[WKWebViewConfiguration alloc] init];

    //建立UserContentController(提供javaScript向webView發送消息的方法)

    WKUserContentController *userContent = [[WKUserContentController alloc] init];

    //添加消息處理,注意:self指代的是須要遵照WKScriptMessageHandler協議,結束時須要移除

    [userContent addScriptMessageHandler:self name:@"NativeMethod"];

    //將UserContentController設置到配置文件中

    config.userContentController = userContent;

    //高端的自定義配置建立WKWebView

    _wkView = [[YXWKView alloc] initWithFrame:self.view.bounds configuration:config];

    NSURL *url = [NSURL URLWithString:@"http://localhost:8080/myDiary/index.html"];

    NSURLRequest *request = [NSURLRequest requestWithURL:url];

    [_wkView loadRequest:request];

    _wkView.UIDelegate = self;

    _wkView.navigationDelegate = self;

    [self.view addSubview:_wkView];

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

//高端配置

    //建立配置

    WKWebViewConfiguration *config = [[WKWebViewConfiguration alloc] init];

    //建立UserContentController(提供javaScript向webView發送消息的方法)

    WKUserContentController *userContent = [[WKUserContentController alloc] init];

    //添加消息處理,注意:self指代的是須要遵照WKScriptMessageHandler協議,結束時須要移除

    [userContent addScriptMessageHandler:self name:@"NativeMethod"];

    //將UserContentController設置到配置文件中

    config.userContentController = userContent;

    //高端的自定義配置建立WKWebView

    _wkView = [[YXWKView alloc] initWithFrame:self.view.bounds configuration:config];

    NSURL *url = [NSURL URLWithString:@"http://localhost:8080/myDiary/index.html"];

    NSURLRequest *request = [NSURLRequest requestWithURL:url];

    [_wkView loadRequest:request];

    _wkView.UIDelegate = self;

    _wkView.navigationDelegate = self;

    [self.view addSubview:_wkView];

[Format Time: 0.0036 seconds]

咱們在js能夠經過NativeMethod這個Handler讓js代碼調用native。

好比在js代碼中,我新增了一個方法

Crayon Syntax Highlighter v2.7.1.1

 

 

JavaScript

<script type="text/javascript">

    function invokeNativeMethod(){

        window.webkit.messageHandlers.NativeMethod.postMessage("我要調用native的方法");

    }

</script>

1

2

3

4

5

<script type="text/javascript">

    function invokeNativeMethod(){

        window.webkit.messageHandlers.NativeMethod.postMessage("我要調用native的方法");

    }

</script>

[Format Time: 0.0011 seconds]

觸發以上方法的時候,會在native如下方法中進行攔截處理。

Crayon Syntax Highlighter v2.7.1.1

 

 

 

Objective-C

#pragma mark - WKScriptMessageHandler

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

    //這裏就是使用高端配置,js調用native的處理地方。咱們能夠根據name和body,進行橋協議的處理。

    NSString *messageName = message.name;

    if ([@"NativeMethod" isEqualToString:messageName]) {

        id messageBody = message.body;

        NSLog(@"%@",messageBody);

    }

}

1

2

3

4

5

6

7

8

9

#pragma mark - WKScriptMessageHandler

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

    //這裏就是使用高端配置,js調用native的處理地方。咱們能夠根據name和body,進行橋協議的處理。

    NSString *messageName = message.name;

    if ([@"NativeMethod" isEqualToString:messageName]) {

        id messageBody = message.body;

        NSLog(@"%@",messageBody);

    }

}

[Format Time: 0.0018 seconds]

 

4、UIWebView和WKWebView的比較和選擇

WKWebView是蘋果在WWDC2014發佈會中發佈IOS8的時候公佈WebKit時候使用的新型的H5容器。它與UIWebView相比較,擁有更快的加載速度和性能,更低的內存佔用。將UIWebViewDelegate和UIWebView重構成了14個類,3個協議,可讓開發者進行更加細緻的配置。

可是他有一個最致命的缺陷,就是WKWebView的請求不能被NSURLProtocol截獲。而咱們團隊開發的app中對於H5容器最佳的優化點主要就在於使用NSURLProtocol技術對於H5進行離線包的處理和H5的圖片和Native的圖片公用一套緩存的技術。由於該問題的存在,目前咱們團隊尚未使用WKWebView代替UIWebVIew。

相關文章
相關標籤/搜索