iOS與H5的交互(四種)

之前項目中有一部分內(nèi)容和H5的小伙伴協(xié)同開發(fā)的,使用了各種與H5的交互,現(xiàn)在有時間整理出來,和大家分享一下。

這篇文章會介紹這么幾個內(nèi)容:
1、Html調(diào)用OC的方法。
2、Html向OC傳值,單個值與多個值。
3、OC調(diào)用Html的方法。
4、OC向Html傳值,多個值。

為了能讓小伙伴們能夠深入體會,作為Html小白,我就從網(wǎng)上現(xiàn)學(xué)現(xiàn)賣的。
Html都是我自己寫的,可能會有很多不雅觀的地方,還請各位看官多多包含~

第一步,新建一個項目TestHtml5。

第二步,新建三個文件分別為
File.html 主體內(nèi)容,包含各個按鈕及其方法的實現(xiàn)。
File.js 可以將方法寫在這里并調(diào)用,然而為了大家方便查看方法,我沒有使用這個文件,我把內(nèi)容都放在File.html中了。
File.css 設(shè)置html的樣式等。

第三步,新建一個繼承于NSObject的CustomJSObject對象,導(dǎo)入<JavaScriptCore/JavaScriptCore.h>頭文件,并定義一個CustomJSProtocol。

第四步,我們先進(jìn)行Html的編碼。

<!DOCTYPE html>
<html>
<header>
<title id = "title">Title of this page</title>
<!--樣式從File.css文件中獲取-->
<link rel="stylesheet" type="text/css" href="File.css">
</header>

<body>
    <!--    標(biāo)簽,css中設(shè)置樣式時,會根據(jù)id來設(shè)置-->
    <p id = "wql">This is my first try to write Html5 file.</p>
    <br/>
    <!--    加粗的文本,css中設(shè)置樣式時,會根據(jù)id來設(shè)置-->
    <b id = "myp">This text is bold</b>

    <!--    換行符-->
    <br/><br/><br/><br/>
    
    <!--    按鈕,點擊按鈕觸發(fā)helloWQL()方法,按鈕上的文本是“點擊出彈框”-->
    <!--    該按鈕的目的是:點擊后觸發(fā)OC的方法-->
    <button type="button" onclick = "helloWQL()">點擊出彈框</button>
    
    <!--        定義各個方法-->
    <script type="text/javascript">
        
        //調(diào)用native的helloWQL方法,native對象由OC注入
        function helloWQL(){
            native.helloWQL();
        }
    </script>
    
</body>
</html>

第五步,在CustomJSProtocol中新添加方法helloWQL。然后在CustomJSObject中實現(xiàn)helloWQL方法,并寫好相關(guān)回調(diào)。

第六步,在ViewController中編碼,加載本地的Html。

//加載本地的html文件
- (void)loadWebView
{
    self.mainWebView = [[UIWebView alloc]initWithFrame:CGRectMake(0, 100, PhoneScreen_WIDTH, PhoneScreen_HEIGHT-100)];
    self.mainWebView.delegate = self;
    NSString *path = [[NSBundle mainBundle] bundlePath];
    NSURL *baseURL = [NSURL fileURLWithPath:path];
    NSString *htmlPath = [[NSBundle mainBundle] pathForResource:@"File" ofType:@"html"];
    
    
    NSString *htmlCont = [NSString stringWithContentsOfFile:htmlPath
                                                    encoding:NSUTF8StringEncoding
                                                       error:nil];

    
    [self.mainWebView loadHTMLString:htmlCont baseURL:baseURL];
    
    [self.view addSubview:self.mainWebView];
}

第七步,在完成html加載的時候,也就是webViewDidFinishLoad方法中進(jìn)行context注入:

- (void)webViewDidFinishLoad:(UIWebView *)webView
{
    //加載完成后注入object,讓我們可以得到html的點擊事件
    [self addCustomAction];
    
}
- (void)addCustomAction
{
    //獲取context,這里的path是固定的
    JSContext *context = [self.mainWebView valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"];
    
    //自定義的JS對象,需要注入到context中
    CustomJSObject *object = [[CustomJSObject alloc]initWithSuccessCallback:^(NSDictionary *dic) {
        
        
        if ([[dic.allKeys firstObject] isEqualToString:@"helloWQL"]) {
            //html調(diào)用OC的方法
            NSLog(@"HelloWQLDic:%@",dic);
            [self webViewClickButtonAction];

        }
        
    } faileCallback:^(NSDictionary *dic) {
        NSLog(@"FailDic:%@",dic);

    }];
    
    //這里要使用native,html那邊調(diào)用的是native
    context[@"native"] = object;

    
}

- (void)webViewClickButtonAction
{
    NSLog(@"OC 接收到 H5按鈕點擊事件");
}

此時我們點擊html的按鈕就能夠調(diào)用OC的方法了。

小伙伴們會不會有點云里霧里的,我覺得口頭描述會有一點復(fù)雜,我就直接做了一張圖,請笑納:

流程梳理.png

看看點擊按鈕會有什么效果:

點擊效果.png

第八步,從Html傳值給OC。
整體的流程和調(diào)用方法一致的,需要注意的是:傳值的時候,請注意方法名的大小寫,尤其是傳多個參數(shù)時,第二個參數(shù)的名字要大寫開頭。

<!DOCTYPE html>
<html>
<header>
<title id = "title">Title of this page</title>
<!--樣式從File.css文件中獲取-->
<link rel="stylesheet" type="text/css" href="File.css">
</header>

<body>
    <!--    標(biāo)簽,css中設(shè)置樣式時,會根據(jù)id來設(shè)置-->
    <p id = "wql">This is my first try to write Html5 file.</p>
    <br/>
    <!--    加粗的文本,css中設(shè)置樣式時,會根據(jù)id來設(shè)置-->
    <b id = "myp">This text is bold</b>

    <!--    換行符-->
    <br/><br/><br/><br/>
    
    <!--    按鈕,點擊按鈕觸發(fā)helloWQL()方法,按鈕上的文本是“點擊出彈框”-->
    <!--    該按鈕的目的是:點擊后觸發(fā)OC的方法-->
    <button type="button" onclick = "helloWQL()">點擊出彈框</button>
    <br/><br/>
    
    
    <!--    按鈕,點擊該按鈕會觸發(fā)sendValueFromHtml()方法,按鈕上的文本是“點擊出彈框”-->
    <!--    該按鈕的目的是:將某個值傳給OC,我們這里分別傳了一個值、兩個值-->
    <button type="button" onclick = "sendValueFromHtml()">點擊傳值</button>
    <br/><br/>
    
    <!--        定義各個方法-->
    <script type="text/javascript">
        
        //調(diào)用native的helloWQL方法,native對象由OC注入
        function helloWQL(){
            native.helloWQL();
        }
    
        function sendValueFromHtml(){
            //需要注意的是傳兩個值的時候,第二個參數(shù)應(yīng)該以大寫字母開頭(WithValueTwo)。
            //正確 sendValueFromHtmlToOCWithValue:(NSString*)valueOne WithValueTwo:(NSString*)valueTwo
            //錯誤 sendValueFromHtmlToOCWithValue:(NSString*)valueOne withValueTwo:(NSString*)valueTwo

            native.sendValueFromHtmlToOCWithValue('This is send one Value');

            native.sendValueFromHtmlToOCWithValueWithValueTwo('Good','Boy');

        }
    </script>
</body>
</html>

傳值的效果:

傳值效果.png

第九步:OC調(diào)用Html的方法。
這個比較簡單需要Html為我們預(yù)留方法即可。我寫了一個按鈕,按鈕觸發(fā)以下方法:

//調(diào)用html的方法
- (void)callHtmlMethodAction:(UIButton*)sender
{
    JSContext *context = [self.mainWebView valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"];
    CustomJSObject *object = [CustomJSObject new];
    NSString *textJS = [NSString stringWithFormat:@"methodForOC()"];
    [context evaluateScript:textJS];
    context[@"native"] = object;

}

看看File.html文件:

<!DOCTYPE html>
<html>
<header>
    
<title id = "title">Title of this page</title>

<!--樣式從File.css文件中獲取-->
<link rel="stylesheet" type="text/css" href="File.css">


</header>

<body>
    <!--    標(biāo)簽,css中設(shè)置樣式時,會根據(jù)id來設(shè)置-->
    <p id = "wql">This is my first try to write Html5 file.</p>
    <br/>
    <!--    加粗的文本,css中設(shè)置樣式時,會根據(jù)id來設(shè)置-->
    <b id = "myp">This text is bold</b>

    <!--    換行符-->
    <br/><br/><br/><br/>
    
    <!--    按鈕,點擊按鈕觸發(fā)helloWQL()方法,按鈕上的文本是“點擊出彈框”-->
    <!--    該按鈕的目的是:點擊后觸發(fā)OC的方法-->
    <button type="button" onclick = "helloWQL()">點擊出彈框</button>
    <br/><br/>
    
    <!--    按鈕,點擊該按鈕會觸發(fā)sendValueFromHtml()方法,按鈕上的文本是“點擊出彈框”-->
    <!--    該按鈕的目的是:將某個值傳給OC,我們這里分別傳了一個值、兩個值-->
    <button type="button" onclick = "sendValueFromHtml()">點擊傳值</button>
    <br/><br/>
    
    
    <!--    按鈕,點擊該按鈕會觸發(fā)getValueFromOC()方法,按鈕上的文本是“從OC拿值”-->
    <!--    該按鈕的目的是:點擊按鈕后,從OC獲取某個值-->
    <button type="button" onclick = "getValueFromOC()">從OC拿值</button>
    
    <!--        定義各個方法-->
    <script type="text/javascript">
        
        //調(diào)用native的helloWQL方法,native對象由OC注入
        function helloWQL(){
            native.helloWQL();
        }
    
        function sendValueFromHtml(){
            //需要注意的是傳兩個值的時候,第二個參數(shù)應(yīng)該以大寫字母開頭(WithValueTwo)。
            //正確 sendValueFromHtmlToOCWithValue:(NSString*)valueOne WithValueTwo:(NSString*)valueTwo
            //錯誤 sendValueFromHtmlToOCWithValue:(NSString*)valueOne withValueTwo:(NSString*)valueTwo

            native.sendValueFromHtmlToOCWithValue('This is send one Value');

            native.sendValueFromHtmlToOCWithValueWithValueTwo('Good','Boy');

        }
    
    
        //這個方法html并不調(diào)用,而是給OC調(diào)用的
        function methodForOC(){
        
            alert('這個是Html的方法,OC調(diào)的到嗎?');
        }

    </script>
</body>
</html>

主要看后面幾行,我們調(diào)的是那個methodForOC方法。

看一下效果:

OC調(diào)Html方法.png

第十步:點擊html的按鈕,然后從OC獲取值。
主體流程:點擊html按鈕,觸發(fā)OC方法,然后從OC傳值給Html。
Html內(nèi)容:

<!DOCTYPE html>
<html>
<header>
    
<title id = "title">Title of this page</title>

<!--樣式從File.css文件中獲取-->
<link rel="stylesheet" type="text/css" href="File.css">

<!--響應(yīng)的方法從File.js文件中獲取-->
<!--<script type="text/javascript" src="File.js"></script>-->

</header>

<body>
    <!--    標(biāo)簽,css中設(shè)置樣式時,會根據(jù)id來設(shè)置-->
    <p id = "wql">This is my first try to write Html5 file.</p>
    <br/>
    <!--    加粗的文本,css中設(shè)置樣式時,會根據(jù)id來設(shè)置-->
    <b id = "myp">This text is bold</b>

    <!--    換行符-->
    <br/><br/><br/><br/>
    
    <!--    按鈕,點擊按鈕觸發(fā)helloWQL()方法,按鈕上的文本是“點擊出彈框”-->
    <!--    該按鈕的目的是:點擊后觸發(fā)OC的方法-->
    <button type="button" onclick = "helloWQL()">點擊出彈框</button>
    <br/><br/>
    
    
    <!--    按鈕,點擊該按鈕會觸發(fā)sendValueFromHtml()方法,按鈕上的文本是“點擊出彈框”-->
    <!--    該按鈕的目的是:將某個值傳給OC,我們這里分別傳了一個值、兩個值-->
    <button type="button" onclick = "sendValueFromHtml()">點擊傳值</button>
    <br/><br/>
    
    
    <!--    按鈕,點擊該按鈕會觸發(fā)getValueFromOC()方法,按鈕上的文本是“從OC拿值”-->
    <!--    該按鈕的目的是:點擊按鈕后,從OC獲取某個值-->
    <button type="button" onclick = "getValueFromOC()">從OC拿值</button>
    
    <!--        定義各個方法-->
    <script type="text/javascript">
        
        //調(diào)用native的helloWQL方法,native對象由OC注入
        function helloWQL(){
            native.helloWQL();
        }
    
        function sendValueFromHtml(){
            //需要注意的是傳兩個值的時候,第二個參數(shù)應(yīng)該以大寫字母開頭(WithValueTwo)。
            //正確 sendValueFromHtmlToOCWithValue:(NSString*)valueOne WithValueTwo:(NSString*)valueTwo
            //錯誤 sendValueFromHtmlToOCWithValue:(NSString*)valueOne withValueTwo:(NSString*)valueTwo

            native.sendValueFromHtmlToOCWithValue('This is send one Value');

            native.sendValueFromHtmlToOCWithValueWithValueTwo('Good','Boy');

        }
    
        //需要從OC那里拿值,之后會觸發(fā)OC的sendValueToHtml方法
        function getValueFromOC(){
            native.sendValueToHtml();
        }
    
        //接收從OC傳過來的值,需要OC調(diào)用該方法,并傳入值
        function getUserNameAndAge(ocValueOne,ocValueTwo){
            alert('name:'+ocValueOne+' '+'age:'+ocValueTwo);

        }
    
        //這個方法html并不調(diào)用,而是給OC調(diào)用的
        function methodForOC(){
        
            alert('這個是Html的方法,OC調(diào)的到嗎?');
        }
    </script>
    
</body>
</html>

傳值的核心代碼:

if ([[dic.allKeys firstObject] isEqualToString:@"sendValueToHtml"]){
        //從OC傳值給html
        NSLog(@"sendValueToHtml:%@",dic);
            
        NSString *name = @"WQL";
        NSString *age = @"22";
        NSString *textJS = [NSString stringWithFormat:@"getUserNameAndAge('%@','%@')",name,age];
        [context evaluateScript:textJS];
            
    }

哈哈,“口說無憑”,直接上圖:

OC傳值給Html

流程梳理完畢,就是上效果圖了:

Html從OC獲取多個值

這個做的有點瑕疵,彈框不知道為什么取消不了。好尷尬....但是數(shù)據(jù)確實傳給了Html那邊。如果有知道原因的小伙伴,請留言哈~

整體流程就是這樣了。我們實現(xiàn)了各種和H5的交互,感覺也沒有那么難哈~

此外,如果運(yùn)行代碼時,點擊按鈕沒有效果,請clean一下,H5好像是有緩存的。
有什么意見或建議還請各位大神不吝指教~

今天愚人節(jié),但學(xué)習(xí)我們是認(rèn)真的!

代碼在這里

最后編輯于
?著作權(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)容