本例子是為了讓大家能快速開發(fā)出OC調(diào)用JS功能的一個簡單的例子。
目前創(chuàng)新互聯(lián)公司已為成百上千家的企業(yè)提供了網(wǎng)站建設(shè)、域名、虛擬空間、網(wǎng)站運營、企業(yè)網(wǎng)站設(shè)計、張店網(wǎng)站維護(hù)等服務(wù),公司將堅持客戶導(dǎo)向、應(yīng)用為本的策略,正道將秉承"和諧、參與、激情"的文化,與客戶和合作伙伴齊心協(xié)力一起成長,共同發(fā)展。
1、準(zhǔn)備一個本地化的html網(wǎng)頁,如jsIOS.html
script type="text/javaScript"
function postStr(){
return document.getElementById("text1").value;
//return "javaScript返回值啦";
}
/script
2、將此html文件放到項目代碼目錄里面,如圖:
3、拖一個UIWebView控件和UIButton控件到xxxViewController對應(yīng)的.xib或.storyboard視圖的UIView上;
在xxxViewController的.h文件中分別聲明UIWebView類型變量和UIButton類型的變量,以及一個按鈕點擊事件(并且跟視圖里面的控件連線),
并且添加一個UIWebViewDelegate類型的委托。喎?"" target="_blank" class="keylink"vcD4KPHA+eHh4Vmlld0NvbnRyb2xsZXIuaM7EvP7E2sjdyOfPwqO6PC9wPgo8cD48L3A+CjxwIGNsYXNzPQ=="p1"
#import
@interface ViewController : UIViewController
@property(nonatomic,retain) IBOutlet UIWebView *webview;
@property(nonatomic,retain) IBOutlet UIButton *button;
-(IBAction)IOS_JS:(id)sender;
@end
4、在xxxViewController.m文件中實現(xiàn)通過點擊事件,調(diào)用javaScript的方法并取得返回值。
代碼如下:
#import "ViewController.h"
@interface ViewController ()
@end
@implementation ViewController
@synthesize webview;
- (void)viewDidLoad
{
[super viewDidLoad];
//設(shè)置webView
webview.backgroundColor = [UIColor clearColor];
//webview.scalesPageToFit =YES;
webview.delegate =self;
//找到j(luò)sIOS.html文件的路徑
NSString *basePath = [[NSBundle mainBundle]bundlePath];
NSString *helpHtmlPath = [basePath stringByAppendingPathComponent:@"jsIOS.html"];
NSURL *url = [NSURL fileURLWithPath:helpHtmlPath];
//加載本地html文件
[webview loadRequest:[NSURLRequest requestWithURL:url]];
}
/*
* 點擊事件
* 調(diào)用javaScript的方法postStr()并取得返回值
* 輸出返回值到控制臺
*/
-(IBAction)IOS_JS:(id)sender
{
NSString *str = [self.webview stringByEvaluatingJavaScriptFromString:@"postStr();"];
NSLog(@"JS返回值:%@",str);
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
}
@end
這種方法是利用攔截webView響應(yīng)的url,對url進(jìn)行處理,同時把需要執(zhí)行的方法名和參數(shù)都放入url中,實現(xiàn)app和H5之前的方法交互:
這個屬性是WKWebView才有的屬性,主要是通過WKScriptMessageHandler的代理方法 - (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message 進(jìn)行交互。
注意:
這兩個方法是成對出現(xiàn)的,每次調(diào)用了add就必須調(diào)用remove。
1.建立 WebViewJavaScriptBridge 和 WebView 之間的關(guān)系。
_jsBridge = [WebViewJavascriptBridge bridgeForWebView:_webView];
2.方法調(diào)用
1)oc調(diào)js方法(通過data可以傳值,通過 response可以接受js那邊的返回值 )
2)js調(diào)oc方法(可以通過data給oc方法傳值,使用responseCallback將值再返回給js)
最后:iOS調(diào)用H5方法
UIWebView: NSString *result = [webView stringByEvaluatingJavaScriptFromString:@"javascript:add(3,5);"];
WKWebView: [self.webView evaluateJavaScript:@"show()" completionHandler:^(id _Nullable response, NSError * _Nullable error) { //TODO }];
在 APP 中,免不了與 H5頁面打交道,所以掌握 與 JS 交互就顯的至關(guān)重要,本文總結(jié)了常見的與 JS 交互方式。
注意事項
在 OC 原生中
在 html 文件中
早期的JS與原生交互的開源庫很多都是用得這種方式來實現(xiàn)的,例如:PhoneGap、 WebViewJavascriptBridge 。
效果圖
使用WKNavigationDelegate中的代理方法,攔截自定義的 URL 來實現(xiàn) JS 調(diào)用 OC 方法。
注意點
關(guān)于如何區(qū)分執(zhí)行不同的OC 方法,也與UIWebView的處理方式一樣,通過URL 的host 來區(qū)分執(zhí)行不同的方法:
JS 調(diào)用OC 方法后,有的操作可能需要將結(jié)果返回給JS。這時候就是OC 調(diào)用JS 方法的場景。
WKWebView 提供了一個新的方法 evaluateJavaScript:completionHandler: ,實現(xiàn)OC 調(diào)用JS 等場景。
注意點
運行結(jié)果
在iOS 7之后,apple添加了一個新的庫JavaScriptCore,用來做JS交互,因此JS與原生OC交互也變得簡單了許多。
首先導(dǎo)入JavaScriptCore庫, 然后在OC中獲取JS的上下文。
再然后定義好JS需要調(diào)用的方法,例如JS要調(diào)用share方法:
則可以在UIWebView加載url完成后,在其代理方法中添加要調(diào)用的share方法:
OC 調(diào)用 JS 方法有多種,首先介紹使用JavaScriptCore框架的方式。
使用JSContext 的方法 -evaluateScript ,可以實現(xiàn) OC 調(diào)用 JS 方法
效果圖
使用WKWebView的時候,如果想要實現(xiàn)JS調(diào)用OC方法,除了攔截URL之外,還有一種簡單的方式。那就是利用WKWebView的新特性MessageHandler來實現(xiàn)JS調(diào)用原生方法。
創(chuàng)建 WKWebViewConfiguration 對象,配置各個API對應(yīng)的MessageHandler。
然后在界面即將顯示的時候添加MessageHandler
需要注意的是addScriptMessageHandler很容易引起循環(huán)引用,導(dǎo)致控制器無法被釋放,所以需要移除MessageHandler
這里實現(xiàn)了兩個協(xié)議 WKUIDelegate,WKScriptMessageHandler , WKUIDelegate 是因為我在JS中彈出了alert 。 WKScriptMessageHandler 是因為我們要處理JS調(diào)用OC方法的請求。
WKScriptMessage 有兩個關(guān)鍵屬性 name 和 body 。
因為我們給每一個OC 方法取了一個name,那么我們就可以根據(jù)name 來區(qū)分執(zhí)行不同的方法。body 中存著JS 要給OC 傳的參數(shù)。
關(guān)于參數(shù)body 的解析,我就舉一個body中放字典的例子,其他的稍后可以看demo。
解析JS 調(diào)用OC 實現(xiàn)分享的參數(shù):
message.boby 就是JS 里傳過來的參數(shù)。我們不同的方法先做一下容錯性判斷。然后正常取值就可以了。
下面只列舉一個shareClick()方法,其他看Demo
這里使用WKWebView 實現(xiàn)OC 調(diào)用JS方法與之前說的文章一樣,通過
- evaluateJavaScript:completionHandler:
效果圖如下圖所示
詳情看下面文章鏈接
iOS下 JS 與 OC 互相調(diào)用(五) - UIWebView+WebViewJavascriptBridge
詳情看下面文章鏈接
iOS下 JS 與 OC 互相調(diào)用(六) - WKWebView+WKWebViewJavascriptBridge
iOS下 JS 與OC 互相調(diào)用(一) - UIWebView 攔截 URL
iOS下 JS 與OC 互相調(diào)用(二) - JavaScriptCore
iOS 下 JS 與 OC 互相調(diào)用(三) - WKWebView 攔截 URL
iOS下JS與OC互相調(diào)用(四)-MessageHandler
iOS下 JS 與 OC 互相調(diào)用(五) - UIWebView+WebViewJavascriptBridge
iOS下 JS 與 OC 互相調(diào)用(六) - WKWebView+WKWebViewJavascriptBridge
以前在項目中很少用到OC和JS交互,所以對這方面沒有進(jìn)行更加深入的了解,最近公司安排的一個項目;一半的內(nèi)容是用h5寫的;所以在這個過程中需要OC和JS進(jìn)行無縫對接,互相頻繁調(diào)用。在做的過程中出現(xiàn)了一些問題,這里總結(jié)出現(xiàn),希望能給大家一些啟示。
一.在webview中如果項目只是想簡單用一下js和oc進(jìn)行交互,就沒有必要搞的那么麻煩,只需要用下面的方式進(jìn)行處理就行.
1.oc調(diào)用js;例如,在js中有一個叫commit的方法,在oc中咱們可以這樣來調(diào)用它
如果你調(diào)用的js函數(shù)需要傳入?yún)?shù),也不要緊,咱們只需要通過字符串拼接的方式將參數(shù)傳入即可。比如當(dāng)前有一個叫sum(a,b)的js函數(shù),在oc中咱們可以這樣來調(diào)用它---(注意:在內(nèi)部參數(shù)要用' '來將參數(shù)括起來,這是因為html函數(shù)傳參方式跟oc的不同,我們必須要按照html的傳參方式傳入才會有效果)
2.js調(diào)用oc;以前js調(diào)用oc是通過在webview這邊攔截js那邊觸發(fā)的http請求的url地址來判斷是不是我們需要調(diào)用的時機(jī),然后再調(diào)用的oc。如果當(dāng)我們在webview上點擊一個按鈕的時候他會跳轉(zhuǎn)到這個頁面,那么我們在oc這邊就可以通過攔截這個地址做一些事情
二.其實,通過上面的方法是可以達(dá)到j(luò)s和oc之間進(jìn)行通訊,但是它也是存在一些弊端,或者說有時候不是很方便的。在ios7以后蘋果官方將javascriptCore框架給開放出來了,我們這個通過這個框架就可以暢通無阻的讓js和oc之間進(jìn)行相互調(diào)用了。
1.通過javascriptCore來進(jìn)行js和oc互相調(diào)用。第一步就是要進(jìn)入javascriptCore這個框架.
之后就可以在需要使用的控制器中導(dǎo)入javascriptCore框架了,并且如果你需要js來調(diào)用oc,并且在js中的觸發(fā)函數(shù)是native.submit(a,b)類型的,那么你需要將js方法和oc方法進(jìn)行關(guān)聯(lián),這樣處理以后,調(diào)用js對應(yīng)的方法就會觸發(fā)oc對應(yīng)的方法,當(dāng)然,JSContext對象也是必須的,這個對象是js和oc關(guān)聯(lián)起來的工具,所有的js和oc調(diào)用都需要通過它來完成。
然后在webViewDidFinishLoad:中我們需要進(jìn)行下面的步驟,關(guān)聯(lián)native方法,是在當(dāng)js方法中有native.submit()類型函數(shù)的時候才需要綁定的,如果沒有這種類型的就不需要綁定。
注:其實通過上面的方法把self.context的native方法跟self綁定是會發(fā)生很嚴(yán)重的內(nèi)存泄露問題的。因為這樣會造成self被相互持有,導(dǎo)致該對象無法被釋放,解決方案是native指定一個新的對象,然后在指定對象里實現(xiàn)JSExport協(xié)議。
接下來就是非native.submit()形式j(luò)s觸發(fā)函數(shù)調(diào)用oc的方式,我們這邊可以用block形式關(guān)聯(lián)javascript function.
通過上面的調(diào)用方式就可以獲取到j(luò)s調(diào)用時給oc傳過來的參數(shù),然后再進(jìn)行相關(guān)處理.當(dāng)js那邊是native.類型的函數(shù)的時候,js調(diào)用oc,我們就可以直接拿到j(luò)s跟oc綁定的那個方法來進(jìn)行處理。
到此,js和oc之間相互調(diào)用的內(nèi)容就差不多了,但是在使用的過程中有些情況下會發(fā)生莫名情況的野指針的情況 ,直接導(dǎo)致程序的崩潰。這個問題我是在webview中調(diào)用手機(jī)攝像頭拍照上傳的過程中發(fā)現(xiàn)的,具體流程是當(dāng)需要上傳圖片的時候js調(diào)用oc的方法,然后oc進(jìn)行拍照并且上傳,當(dāng)上傳圖片成功以后,再通過oc調(diào)用js通過js去回顯圖片,就是在回調(diào)js的過程中有時候就會發(fā)生莫名其妙的野指針崩潰,暫時我還沒找到能夠徹底解決這個問題的辦法,等找到相關(guān)方法,我再進(jìn)行公布。
續(xù):之前在webView中頻繁使用js和OC互相調(diào)用,出現(xiàn)了野指針問題,那么這個問題現(xiàn)在解決了。具體做法就是我們拿到webView所在的線程,讓你要執(zhí)行的方法在webView所在線程中執(zhí)行。例如:
通過上述方法就可以避免野指針問題,但是具體是因為什么原因造成野指針問題的,我還沒弄明白,希望知道的高手指教。
使用示例: 下面的示例代碼將調(diào)用上面NativeOcClass的方法,在js層只需要這樣調(diào)用: var ret = jsb.reflection.callStaticMethod("NativeOcClass", "callNativeUIWithTitle:andContent:", "cocos2d-js", "Yes! you call a Native UI from Reflect.
文章標(biāo)題:ios開發(fā)oc調(diào)用js,ios開發(fā)語言swift和oc
文章網(wǎng)址:http://chinadenli.net/article28/dsisojp.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供手機(jī)網(wǎng)站建設(shè)、做網(wǎng)站、ChatGPT、App設(shè)計、標(biāo)簽優(yōu)化、Google
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)