UIWebView與JavaScript的交互及JavaScript調(diào)試技巧

UIWebView與JS的交互携兵,說(shuō)白了就是Objective-C和JavaScript的相互調(diào)用。Objective-C調(diào)用JavaScript代碼的方法荠商,是通過(guò)UIWebView的 - (NSString *)stringByEvaluatingJavaScriptFromString:(NSString *)script;的方法來(lái)實(shí)現(xiàn)的跷乐。該方法向UIWebView傳遞一段需要執(zhí)行的JavaScript代碼最后獲取執(zhí)行結(jié)果兔魂。

JavaScript調(diào)用Objective-C的方法,并沒(méi)有現(xiàn)成的API闰挡,但是有些方法可以達(dá)到相應(yīng)的效果锐墙。具體是利用UIWebView的特性:在UIWebView的內(nèi)發(fā)起的所有網(wǎng)絡(luò)請(qǐng)求,都可以通過(guò)delegate函數(shù)得到通知长酗。

說(shuō)明:

  • 本文是一個(gè)小白記錄OC與JS交互的學(xué)習(xí)歷程溪北,適合跟我一樣的小白,大神若要噴花枫,請(qǐng)輕噴_

  • 學(xué)習(xí)UIWebView與JS的交互之前刻盐,建議熟悉下HTML和Javascript的基本語(yǔ)法,不用看太多劳翰,在w3school看一到兩天HTML敦锌,再看一到兩天JS就行。

OC調(diào)用JS方法佳簸、JS調(diào)用OC方法(不使用第三方開(kāi)源庫(kù)的情況下)

準(zhǔn)備工作:

1.新建一個(gè)Single View Application乙墙,
再新建一個(gè)ViewController(eg:BasicUsageViewController)凄贩,然后在StoryBoard新建一個(gè)ViewController,拖一個(gè)UIWebView和UILabel以備用慎陵,關(guān)聯(lián)webView及代理

@property (weak, nonatomic) IBOutlet UIWebView *webView;
@property (weak, nonatomic) IBOutlet UILabel *testLabel;

2.在工程中新建一個(gè)web1.html文件(Commend+N贱鼻、OtherEmpty汉买、Next衔峰、輸入、create)蛙粘,代碼如下:

<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
            <title>我是HTML標(biāo)題</title>
            </head>
    <body bgcolor="#9aff9a">
        <div id="addNewNodeTest">
            <p id="p1"> 這是段落A垫卤。</p>
            <p id="p2"> 這是段落B。</p>
        </div>
        <div class="page">
            <button onclick="changeUILabelText()"> 改變UILabel文字 </button>
            <button onclick="logText()"> NSLog打印文字 </button>
        </div>
    </body>
    
</html>

3.再在工程中新建一個(gè)test.js文件出牧,代碼如下:

//添加子節(jié)點(diǎn)
function addNewNodeTest () {
    var para = document.createElement("p");
    var node = document.createTextNode("這是新段落穴肘。");
    para.appendChild(node);
    var element = document.getElementById("addNewNodeTest");
    element.appendChild(para);
    console.log("添加子節(jié)點(diǎn)成功");
}

//改變UILabel的文本
function changeUILabelText() {
    //"changelabeltext"是你自己定的一個(gè)協(xié)議。
    //注url不要含大寫(xiě)字母舔痕,就算是大寫(xiě)字母评抚,在`webView:shouldStartLoadWithRequest:navigationType:`代理方法里也會(huì)被替換成小寫(xiě)字母
    var url = "changelabeltext:" + "我是改變后的文字";
    //給document.location重新賦值就相當(dāng)于webView加載一個(gè)新的URL,所以又會(huì)調(diào)用`webView:shouldStartLoadWithRequest:navigationType:`方法伯复,然后就可以在這個(gè)代理方法里截獲這個(gè)重定向請(qǐng)求
    document.location = url;
}

//也可以自己封裝個(gè)傳參數(shù)的方法
function sendCommand(cmd,param){
    var url = "yourprotocol:" + cmd + ":" + param;
    document.location = url;
}
//打印測(cè)試
function logText(){
    sendCommand("log","Hi,I'm In logText Function");
}

好了慨代,現(xiàn)在可以開(kāi)擼了

4.加載webView并插入測(cè)試js

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view.
    NSString* path = [[NSBundle mainBundle] pathForResource:@"web1" ofType:@"html"];
    [self.webView loadRequest:[NSURLRequest requestWithURL:[NSURL fileURLWithPath:path]]];
    
    NSString *filePath = [[NSBundle mainBundle] pathForResource:@"test" ofType:@"js"];
    NSString *jsString = [[NSString alloc] initWithContentsOfFile:filePath encoding:NSUTF8StringEncoding error:nil];
    [self.webView stringByEvaluatingJavaScriptFromString:jsString];
}

5、加載結(jié)束,獲取HTML頁(yè)面title元素边翼,賦值給self.title

- (void)webViewDidFinishLoad:(UIWebView *)webView {
    // 獲取HTML頁(yè)面title元素鱼响,賦值給self.title
    self.title = [webView stringByEvaluatingJavaScriptFromString:@"document.title"];
}

6、建幾個(gè)按鈕组底,體驗(yàn)插入js的幾種方式

模擬器
//分別對(duì)應(yīng)上圖3個(gè)按鈕
- (IBAction)insertJavaScript1:(UIButton *)sender {
    //方法1:預(yù)加載的test.js內(nèi)部已經(jīng)寫(xiě)了addNewNodeTest()方法丈积,這里只需注入"addNewNodeTest()"字符串即可
    [self.webView stringByEvaluatingJavaScriptFromString:@"addNewNodeTest()"];
}

- (IBAction)insertJavaScript2:(UIButton *)sender {
    //方法2:把test.js內(nèi)部的addNewNodeTest()方法復(fù)制過(guò)來(lái),去掉行與行之間的空格
    //字符串雙引號(hào)要么前面加轉(zhuǎn)義符"\",要么變成單引號(hào)债鸡,例如:
    NSString *addNewNode = @"var para = document.createElement(\"p\");var node=document.createTextNode('這是新段落江滨。');para.appendChild(node);var element=document.getElementById('addNewNodeTest');element.appendChild(para);";
    [self.webView stringByEvaluatingJavaScriptFromString:addNewNode];
}

- (IBAction)insertJavaScript3:(UIButton *)sender {
    //方法3:把test.js內(nèi)部的addNewNodeTest()方法復(fù)制過(guò)來(lái),并在每一行首尾加上雙引號(hào)(跟方法2差不多)
    NSString *addNewNode =
    @"var para = document.createElement('p');"
    "var node = document.createTextNode('這是新段落厌均。');"
    "para.appendChild(node);"
    "var element = document.getElementById('addNewNodeTest');"
    "element.appendChild(para);";
    [self.webView stringByEvaluatingJavaScriptFromString:addNewNode];
}

說(shuō)明:addNewNodeTest()方法執(zhí)行的操作是創(chuàng)建了一個(gè)節(jié)點(diǎn)<p> 這是新段落唬滑。</p>,添加到了位置1,然后webView上就會(huì)新增一行棺弊,不懂的同學(xué)請(qǐng)自行腦補(bǔ)(看不懂也沒(méi)關(guān)系晶密,這里只是演示怎么用OC調(diào)js代碼)

    <div id="addNewNodeTest">
        <p id="p1"> 這是段落A。</p>
        <p id="p2"> 這是段落B模她。</p>
        //位置1
    </div>

7.好了稻艰,現(xiàn)在讓js調(diào)OC的方法:在ViewController里添加如下代碼:

- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType {
    NSLog(@"開(kāi)始加載請(qǐng)求");
    //當(dāng)點(diǎn)擊按鈕時(shí),navigationType = UIWebViewNavigationTypeOther
    NSString *requestString = [[request URL] absoluteString];
    NSArray *components = [requestString componentsSeparatedByString:@":"];
    if ([components[0] isEqualToString:@"changelabeltext"] && components.count > 1) {
        //這種通過(guò)URL傳參數(shù)的方式貌似不是太好侈净,因?yàn)閰?shù)如果含中文還得URL解碼尊勿,eg:
        self.testLabel.text = [components[1] stringByRemovingPercentEncoding];
        return NO;
    }
    //也可以這樣判斷
    else if([request.URL.scheme isEqualToString:@"yourprotocol"]) {
        NSLog(@"%@",[components[2] stringByRemovingPercentEncoding]);
        return NO;
    }
    return YES;
}

點(diǎn)擊webView里的改變UILabel文字按鈕會(huì)發(fā)現(xiàn)testLabel的文字變了僧凤,這里解釋下原因:web1.html代碼中
<button onclick="changeUILabelText()"> 改變UILabel文字 </button>這個(gè)按鈕綁定了一個(gè)方法,名字叫changeUILabelText()元扔,點(diǎn)擊就會(huì)調(diào)用changeUILabelText()方法(當(dāng)然包含這個(gè)方法的test.js已經(jīng)加載了),然后webView的URL變了就會(huì)重新加載躯保,這樣在回調(diào)方法webView:shouldStartLoadWithRequest:navigationType:會(huì)再次調(diào)用,然后就可以在這個(gè)代理方法里截獲這個(gè)重定向請(qǐng)求的request.URL.absoluteString來(lái)處理OC代碼了

說(shuō)明:

(1)Objective-C調(diào)用JavaScript代碼的時(shí)候是同步的

- (NSString *)stringByEvaluatingJavaScriptFromString:(NSString *)script;

(2)JavaScript調(diào)用Objective-C代碼的時(shí)候是異步的

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

調(diào)試模擬器或真機(jī)里的WebView的技巧

  • 模擬器

模擬器加載網(wǎng)頁(yè)后澎语,打開(kāi)電腦端Safari(確保偏好設(shè)置里的高級(jí) - 在菜單中顯示“開(kāi)發(fā)”菜單選項(xiàng)已打開(kāi))途事,然后選擇開(kāi)發(fā)Simulator,就會(huì)看見(jiàn)模擬器正在運(yùn)行的web1.html擅羞,點(diǎn)擊web1.html就來(lái)到了控制臺(tái)盯孙。
點(diǎn)擊方式一按鈕,就會(huì)發(fā)現(xiàn)控制臺(tái)標(biāo)簽頁(yè)最先面有輸出祟滴,這是因?yàn)樵?code>test.js的addNewNodeTest ()的最后一行有這么一句話:console.log("添加子節(jié)點(diǎn)成功");,在這里歌溉,console.log()相當(dāng)于NSLog垄懂,括號(hào)內(nèi)可以直接加變量。

當(dāng)然痛垛,你也可以在控制臺(tái)插入js代碼草慧,如下圖:在左下角輸入一句js代碼alert('666');就能在模擬器上得到反饋,當(dāng)然匙头,此時(shí)你輸入addNewNodeTest();效果跟點(diǎn)擊方式一按鈕是一樣的

模擬器調(diào)試之控制臺(tái)

你也可以切換到調(diào)試器標(biāo)簽漫谷,然后打個(gè)斷點(diǎn),點(diǎn)擊方式一按鈕蹂析,就可以單步調(diào)試了舔示。有興趣的同學(xué)可以切換到元素標(biāo)簽頁(yè)看看

模擬器調(diào)試之調(diào)試器
  • 真機(jī)

首先在手機(jī)的設(shè)置 - Safari - 高級(jí) - 啟用Web檢查器,然后用數(shù)據(jù)線連接電腦电抚,Xcode運(yùn)行你的項(xiàng)目惕稻,打開(kāi)一個(gè)含webView的頁(yè)面,就可以在電腦端Safari的開(kāi)發(fā)菜單下看到你的設(shè)備了蝙叛,調(diào)試方法同上

高級(jí)用法(WebViewJavascriptBridge)

WebViewJavascriptBridge 是一個(gè)用于UIWebView / WKWebViews和JS交互的封裝庫(kù)俺祠,連Facebook Messenger都在使用。

這里我就引用一下楊騎滔的這篇博客的內(nèi)容借帘,也就是通過(guò)實(shí)現(xiàn)以下功能來(lái)學(xué)習(xí)WebViewJavascriptBridge的使用(侵刪)蜘渣。

原文已經(jīng)比較詳盡了,但是有一些地方對(duì)于我等小白來(lái)說(shuō)可能不夠詳細(xì)肺然,所以折騰了不少時(shí)間蔫缸,所以在這里對(duì)原文做了一點(diǎn)修改,更加清晰易懂狰挡。

要實(shí)現(xiàn)的功能

  • WebView展示一段HTML捂龄,禁止HTML文本中自帶的 <img> 標(biāo)簽自動(dòng)加載释涛,也就是說(shuō)下載圖片的操作放在native端來(lái)處理,并通過(guò)JS將圖片在Cache中的地址返回給UIWebview倦沧。

  • 實(shí)現(xiàn)點(diǎn)擊WebView圖片放大唇撬、保存圖片到相冊(cè)等操作。

之所以要把圖片操作放在native端做的好處在于:1展融、可以進(jìn)行本地緩存窖认,下次進(jìn)入這篇文章可以直接從緩存讀取,提高響應(yīng)速度并且節(jié)省用戶流量告希。2扑浸、可以實(shí)現(xiàn)點(diǎn)擊圖片放大、保存圖片到相冊(cè)等操作燕偶。

技術(shù)難點(diǎn)也有兩個(gè):

  • 如何讓HTML文本onLoad的時(shí)候喝噪,禁用自身的圖片加載而是從本地獲取圖片?
  • 如何把native端下載好的圖片返回給網(wǎng)頁(yè)指么?

先來(lái)看看基本用法

在WebViewJavascriptBridge中酝惧,交互的方式只有兩種:send 和 callHandler,JS和OC都有這兩個(gè)方法伯诬,所以對(duì)應(yīng)的四種關(guān)系是(很重要):

四種關(guān)系圖表

以上表中的對(duì)應(yīng)關(guān)系的解讀是晚唇,例如第一條:在JS中如果調(diào)用了bridge.send(),那么將觸發(fā)OC端_bridge初始化方法中的回調(diào)盗似。

同理哩陕,第二條,在JS中調(diào)用了bridge.callHandler('testJavascriptHandler')赫舒,它將觸發(fā)OC端注冊(cè)的同名方法:

也就是說(shuō)悍及,一種語(yǔ)言register了Handler(回調(diào)或者block),另一種語(yǔ)言callHandler就會(huì)執(zhí)行回調(diào)或者block接癌,還能傳遞數(shù)據(jù)并鸵;不理解不要緊,下面的Demo這四種方式全都有例子扔涧。

了解了使用規(guī)則园担,下面來(lái)看看在我們這個(gè)實(shí)際需求中應(yīng)用的整體思路:


整體思路

廢話不說(shuō),直接開(kāi)擼:

1枯夜、導(dǎo)入WebViewJavascriptBridge弯汰,新建一個(gè)ViewController,聲明一個(gè)WebViewJavascriptBridge實(shí)例:

@property WebViewJavascriptBridge* bridge;

2湖雹、找一個(gè)含圖片的html咏闪,比如這一篇(源碼已做刪減),導(dǎo)入到項(xiàng)目中

3摔吏、在項(xiàng)目中新建一個(gè)js文件鸽嫂,比如imageCache.js纵装,貼上如下代碼:

//一加載這個(gè)js就會(huì)調(diào)用下面自己寫(xiě)的onLoaded() 方法
window.onload = function() {
    onLoaded();
}

//使用WebViewJavascriptBridge的話,這一段是必須的(固定寫(xiě)法)
function connectWebViewJavascriptBridge(callback) {
    if (window.WebViewJavascriptBridge) {
        callback(WebViewJavascriptBridge)
    } else {
        document.addEventListener('WebViewJavascriptBridgeReady', function() {
                                  callback(WebViewJavascriptBridge)
                                  }, false)
    }
}

//上面已經(jīng)說(shuō)了据某,一插入js橡娄,這個(gè)方法就開(kāi)始執(zhí)行
function onLoaded() {
    connectWebViewJavascriptBridge(function(bridge) {
                                   //document.querySelectorAll:按文檔順序返回指定元素節(jié)點(diǎn)的子樹(shù)中匹配選擇器的元素集合,如果沒(méi)有匹配返回空集合
                                   //下面這幾句是提取所有img標(biāo)簽的esrc屬性值(圖片的URL)癣籽,并存到imageUrlsArray這個(gè)數(shù)組中
                                   var allImage = document.querySelectorAll("img");
                                   allImage = Array.prototype.slice.call(allImage, 0);
                                   var imageUrlsArray = new Array();
                                   allImage.forEach(function(image) {
                                                    var esrc = image.getAttribute("esrc");
                                                    var newLength = imageUrlsArray.push(esrc);
                                                    });
                                   //將imageUrlsArray這個(gè)數(shù)組發(fā)送到OC的block
                                   bridge.send(imageUrlsArray);////四種關(guān)系圖表之第1種
                                   
                                   bridge.init(function(message, responseCallback) {
                                               alert(message);
                                               if (responseCallback) {
                                               responseCallback("Message1已收到挽唉,送你個(gè)Message2")
                                               }
                                    })
                                   //這里先注冊(cè)下,等待OC代碼的_bridge調(diào)用([_bridge callHandler:....])
                                   bridge.registerHandler('imagesDownloadComplete', function(data, responseCallback) {
                                                          var allImage = document.querySelectorAll("img");
                                                          allImage = Array.prototype.slice.call(allImage, 0);
                                                          allImage.forEach(function(image) {
                                                                           if (image.getAttribute("esrc") == data[0] || image.getAttribute("esrc") == decodeURIComponent(data[0])) {
                                                                           image.src = data[1];
                                                                           }
                                                                           
                                                                           });
                                                          responseCallback("圖片"+data[0]+"已加載")
                                                          })
                                   
                                   //使用WebViewJavascriptBridge的話筷狼,這一段是必須的瓶籽,不然上面的imageUrlsArray傳不過(guò)去
                                   bridge.send('Please respond to this', function responseCallback(responseData) {
                                               console.log("Javascript got its response", responseData)
                                               })
                                   });
    
}

4、viewDidLoad里加載 webView

NSString *path = [[NSBundle mainBundle] pathForResource:@"article1" ofType:@"html"];
    //原網(wǎng)頁(yè)html代碼
    NSString *_content = [NSString stringWithContentsOfFile:path encoding:NSUTF8StringEncoding error:nil];
    //我們要做的第一步是替換獲取的HTML文本中默認(rèn)的src埂材,避免webView自動(dòng)加載圖片
    _content = [_content stringByReplacingOccurrencesOfString:@"src" withString:@"esrc"];
    //正則替換,給每個(gè)圖片添加一個(gè)onImageClick點(diǎn)擊方法
    NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:@"(<img[^>]+esrc=\")(\\S+)\"" options:0 error:nil];
    //終于得到我想要的html了!!!
    _content = [regex stringByReplacingMatchesInString:_content options:0 range:NSMakeRange(0, _content.length) withTemplate:@"<img esrc=\"$2\" onClick=\"javascript:onImageClick('$2')\""];
    [self.webView loadHTMLString:_content baseURL:nil];
    
    //插入js
    NSString *filePath = [[NSBundle mainBundle] pathForResource:@"imageCache" ofType:@"js"];
    NSString *jsString = [[NSString alloc] initWithContentsOfFile:filePath encoding:NSUTF8StringEncoding error:nil];
    [self.webView stringByEvaluatingJavaScriptFromString:jsString];
    
    //初始化一個(gè)WebViewJavascript橋梁塑顺,方便imageCache.js把數(shù)據(jù)傳過(guò)來(lái)
    self.bridge = [WebViewJavascriptBridge bridgeForWebView:self.webView webViewDelegate:self handler:^(id data, WVJBResponseCallback responseCallback) {
        NSLog(@"###來(lái)自imageCache.js的圖片URL數(shù)組: %@", data);
        //利用SDWebImageManager下載圖片到本地
        [self downloadAllImagesInNative:data];
        _imageURLs = data;
        responseCallback(@"###Right back atcha");
    }];
#pragma mark -- 下載全部圖片
-(void)downloadAllImagesInNative:(NSArray *)imageUrls{
    SDWebImageManager *manager = [SDWebImageManager sharedManager];
    //初始化一個(gè)數(shù)組用于存image
    _allImagesOfThisArticle = [NSMutableArray arrayWithCapacity:imageUrls.count];
    for (NSUInteger i = 0; i < imageUrls.count; i++) {
        NSString *_url = imageUrls[i];
        [manager downloadImageWithURL:[NSURL URLWithString:_url] options:SDWebImageHighPriority progress:nil completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, BOOL finished, NSURL *imageURL) {
            
            if (image) {
                [_allImagesOfThisArticle addObject:image];
                dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
                    NSString *imgB64 = [UIImageJPEGRepresentation(image, 1.0) base64EncodedStringWithOptions:NSDataBase64Encoding64CharacterLineLength];
                    //把圖片在磁盤中的地址傳回給JS
                    NSString *key = [manager cacheKeyForURL:imageURL];
                    
                    NSString *source = [NSString stringWithFormat:@"data:image/png;base64,%@", imgB64];
                    //四種關(guān)系圖表之第4種
                    [_bridge callHandler:@"imagesDownloadComplete" data:@[key,source] responseCallback:^(id responseData) {
                        NSLog(@"js把img標(biāo)簽的esrc屬性替換后-->%@<",responseData);
                    }];
                    
                });
                
            }
            
        }];
        
    }
    
}

好了,到這里為止就webView就可以加載本地緩存的圖片了俏险,如果要實(shí)現(xiàn)圖片的點(diǎn)擊放大茬暇,請(qǐng)接著往下看

5、imageCache.js里添加圖片點(diǎn)擊事件:

//圖片點(diǎn)擊會(huì)觸發(fā)
function onImageClick(picUrl){
    connectWebViewJavascriptBridge(function(bridge) {
                                   //作者用的是"p img[esrc]"寡喝,意思是獲取p標(biāo)簽里的img的src值
                                   //我這里的圖片是div,所以要改成"div img[esrc]"
                                   //var allImage = document.getElementsByTagName('img');//這樣比較通用
                                   var allImage = document.querySelectorAll("div img[esrc]");
                                   allImage = Array.prototype.slice.call(allImage, 0);
                                   var urls = new Array();
                                   var index = -1;
                                   var x = 0;
                                   var y = 0;
                                   var width = 0;
                                   var height = 0;
                                   //獲取點(diǎn)擊圖片在所有圖片中的編號(hào)以及在圖片相對(duì)于webView左上角的位置勒奇、寬高预鬓,并把這些信息返回給OC
                                   allImage.forEach(function(image) {
                                                    var imgUrl = image.getAttribute("esrc");
                                                    var newLength = urls.push(imgUrl);
                                                    if(imgUrl == picUrl || imgUrl == decodeURIComponent(picUrl)){
                                                    index = newLength-1;
                                                    x = image.getBoundingClientRect().left;
                                                    y = image.getBoundingClientRect().top;
                                                    x = x + document.documentElement.scrollLeft;
                                                    y = y + document.documentElement.scrollTop;
                                                    width = image.width;
                                                    height = image.height;
                                                    console.log("x:"+x +";y:" + y+";width:"+image.width +";height:"+image.height);
                                                    }
                                                    });
                                   
                                   console.log("檢測(cè)到點(diǎn)擊"+"x="+x+"y="+y+"width="+width+"height="+height);
                                   //四種關(guān)系圖表之第2種
                                   bridge.callHandler('imageDidClicked', {'index':index,'x':x,'y':y,'width':width,'height':height}, function(response) {
                                                      console.log("JS已經(jīng)發(fā)出imgurl和index,同時(shí)收到回調(diào)赊颠,說(shuō)明OC已經(jīng)收到數(shù)據(jù)");
                                                      });
                                   });
    
}

6格二、viewDidLoad里注冊(cè)js圖片點(diǎn)擊事件回調(diào),這里我用了一個(gè)簡(jiǎn)單的圖片瀏覽器HZPhotoBrowser,修改了部分代碼使能夠適用于webView

//這里注冊(cè)一下,imageCache.js里的`bridge.callHandler('imageDidClicked', {'index':index,'x':x,'y':y,'width':width,'height':height}, function(response)`就會(huì)傳數(shù)據(jù)過(guò)來(lái)
    [_bridge registerHandler:@"imageDidClicked" handler:^(id data, WVJBResponseCallback responseCallback) {
        
        NSInteger index = [[data objectForKey:@"index"] integerValue];
        
        CGFloat originX = [[data objectForKey:@"x"] floatValue];
        CGFloat originY = [[data objectForKey:@"y"] floatValue];
        CGFloat width   = [[data objectForKey:@"width"] floatValue];
        CGFloat height  = [[data objectForKey:@"height"] floatValue];
        
        //啟動(dòng)圖片瀏覽器
        HZPhotoBrowser *browserVc = [[HZPhotoBrowser alloc] init];
        // browserVc.sourceImagesContainerView = cell.webView; // 原圖的父控件
        browserVc.imageCount = _allImagesOfThisArticle.count; // 圖片總數(shù)
        browserVc.currentImageIndex = index;
        browserVc.delegate = self;
        browserVc.imageFrameinWebView = CGRectMake(originX, originY+64, width, height);
        [browserVc show];
        
        NSLog(@"OC已經(jīng)收到JS的imageDidClicked了: %@", data);
        responseCallback(@"OC已經(jīng)收到JS的imageDidClicked了");
    }];
    //四種關(guān)系圖表之第3種(測(cè)試)
//    [_bridge send:@"###Message1:我將會(huì)被發(fā)送到imageCache.js里bridge.init()的回調(diào)里"];
    
    //四種關(guān)系圖表之第3種(測(cè)試)
//    [_bridge send:@"###Message1:我將會(huì)被發(fā)送到imageCache.js里bridge.init()的回調(diào)里竣蹦,imageCache.js還會(huì)給我回調(diào),不信你可能下面的Log" responseCallback:^(id responseData) {
//        NSLog(@"###%@", responseData);
//    }];
#pragma mark - HZPhotoBrowser的代理方法
//這里沒(méi)有占位小圖顶猜,所以就讓大圖代替
- (UIImage *)photoBrowser:(HZPhotoBrowser *)browser placeholderImageForIndex:(NSInteger)index {
    return _allImagesOfThisArticle[index];
}

- (NSURL *)photoBrowser:(HZPhotoBrowser *)browser highQualityImageURLForIndex:(NSInteger)index {
    return [NSURL URLWithString:_imageURLs[index]];
}

最終效果

最終效果

好了,到此為止WebViewJavascriptBridge的基本用法已基本說(shuō)完了痘括,雖然很簡(jiǎn)單长窄,但是也花了我一天的時(shí)間,寫(xiě)的同時(shí)又發(fā)現(xiàn)了不少新東西纲菌,還是很值的挠日。這里是這個(gè)小Demo的源碼。渣渣代碼翰舌,就不上傳github了嚣潜。

  • 參考及推薦文章:

UIWebView與JS的深度交互

UIWebView與JavaScript的那些事兒

iOS開(kāi)發(fā)之Objective-C與JavaScript的交互

關(guān)于UIWebView和PhoneGap的總結(jié)

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市椅贱,隨后出現(xiàn)的幾起案子懂算,更是在濱河造成了極大的恐慌只冻,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,919評(píng)論 6 502
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件计技,死亡現(xiàn)場(chǎng)離奇詭異喜德,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)酸役,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,567評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門住诸,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人涣澡,你說(shuō)我怎么就攤上這事贱呐。” “怎么了入桂?”我有些...
    開(kāi)封第一講書(shū)人閱讀 163,316評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵奄薇,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我抗愁,道長(zhǎng)馁蒂,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,294評(píng)論 1 292
  • 正文 為了忘掉前任蜘腌,我火速辦了婚禮沫屡,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘撮珠。我一直安慰自己沮脖,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,318評(píng)論 6 390
  • 文/花漫 我一把揭開(kāi)白布芯急。 她就那樣靜靜地躺著勺届,像睡著了一般。 火紅的嫁衣襯著肌膚如雪娶耍。 梳的紋絲不亂的頭發(fā)上免姿,一...
    開(kāi)封第一講書(shū)人閱讀 51,245評(píng)論 1 299
  • 那天,我揣著相機(jī)與錄音榕酒,去河邊找鬼胚膊。 笑死,一個(gè)胖子當(dāng)著我的面吹牛想鹰,可吹牛的內(nèi)容都是我干的澜掩。 我是一名探鬼主播,決...
    沈念sama閱讀 40,120評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼杖挣,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼肩榕!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 38,964評(píng)論 0 275
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤株汉,失蹤者是張志新(化名)和其女友劉穎筐乳,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體乔妈,經(jīng)...
    沈念sama閱讀 45,376評(píng)論 1 313
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡蝙云,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,592評(píng)論 2 333
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了路召。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片勃刨。...
    茶點(diǎn)故事閱讀 39,764評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖股淡,靈堂內(nèi)的尸體忽然破棺而出身隐,到底是詐尸還是另有隱情,我是刑警寧澤唯灵,帶...
    沈念sama閱讀 35,460評(píng)論 5 344
  • 正文 年R本政府宣布贾铝,位于F島的核電站,受9級(jí)特大地震影響埠帕,放射性物質(zhì)發(fā)生泄漏垢揩。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,070評(píng)論 3 327
  • 文/蒙蒙 一敛瓷、第九天 我趴在偏房一處隱蔽的房頂上張望叁巨。 院中可真熱鬧,春花似錦呐籽、人聲如沸锋勺。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,697評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至苍姜,卻和暖如春牢酵,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背衙猪。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,846評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工馍乙, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人垫释。 一個(gè)月前我還...
    沈念sama閱讀 47,819評(píng)論 2 370
  • 正文 我出身青樓丝格,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親棵譬。 傳聞我的和親對(duì)象是個(gè)殘疾皇子显蝌,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,665評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容