iOS 中JS和OC互調----UIWebView(基礎)

http://blog.csdn.net/y550918116j/article/details/49619847

UIWebView(基礎)

當你在項目中想嵌入網頁時,可以使用UIWebView類嵌入Web內容。你只需要創建一個UIWebView對象,并將它附加到一個view窗口。你還可以使用這個類來執行頁面歷史的前進或后退。

本文主要介紹關于UIWebView的基礎,包括:加載網頁、實現代理以及JS和OC的互相調用。

1 準備工作

1.1 Html頁面

我已經為大家創建了html頁面的源代碼,只需要復制到記事本,并將文件名改為index.html。


這個頁面有輸入框、按鈕和做顯示用的,其簡單功能是在輸入框輸入數據,點擊按鈕后顯示到顯示區域。

在瀏覽器運行可以看到如下效果。

1.2 搭建項目

這個地方就不詳細描述了,創建一個簡單項目->拉一個UIWebView到界面->UIWebView指向UIViewController的屬性名。

搭建后的核心部分如下,這里我使用的VC名為BaseVC。

#import"BaseVC.h"@interfaceBaseVC() @property(weak,nonatomic)IBOutletUIWebView*webView;///< UIWebView

@end@implementationBaseVC

- (void)viewDidLoad {

[superviewDidLoad];

}@end

2 顯示Web頁面

將我們創建好的index.html拉到項目中,至于位置就隨你高興了。

然后我們改造BaseVC的viewDidLoad方法。

- (void)viewDidLoad {

[superviewDidLoad];

// 找到index.html的路徑

NSURL*url = [[NSBundlemainBundle] URLForResource:@"index"withExtension:@"html"];

NSURLRequest*urlRequest = [NSURLRequestrequestWithURL:url];// url的位置[self.webViewloadRequest:urlRequest];// 加載頁面

}

由于我們的html頁面在項目里面,我們可以直接使用[NSBundle mainBundle]去尋找。如果你使用的是網咯連接“www.baidu.com”,你可以這樣獲得NSURL。

url =[NSURL URLWithString:@"www.baidu.com"];

然后運行項目,就可以看到和瀏覽器一樣的效果。

3 代理UIWebViewDelegate

UIWebView也有代理,如果你不懂什么是代理模式,查閱我的博文《23設計模式之代理模式(Proxy)》。我們在UIWebViewDelegate發現了四個方法。

__TVOS_PROHIBITED@protocolUIWebViewDelegate

@optional

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

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

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

- (void)webView:(UIWebView*)webView didFailLoadWithError:(nullableNSError*)error;

@end

這四個代理的作用分別是:

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

將要加載一個web頁面,返回yes代表繼續加載,no代表不加載。

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

開始加載web頁面;

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

加載web頁面結束;

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

加載web頁面出錯,你可以在error看到錯誤信息。

現在我們改造BaseVC。下面都只顯示核心代碼,不重要的代碼不顯示。

@interfaceBaseVC()<UIWebViewDelegate>

@property(weak,nonatomic)IBOutletUIWebView*webView;///< UIWebView

@end

@implementationBaseVC

- (void)viewDidLoad {

? ? ? ? ?[superviewDidLoad];

? ? ? ? // 找到index.html的路徑

? ? ?NSURL*url = [[NSBundlemainBundle] URLForResource:@"index"withExtension:@"html"];

NSURLRequest*urlRequest = [NSURLRequestrequestWithURL:url];// url的位置self.webView.delegate=self;// 代理UIWebViewDelegate

[self.webViewloadRequest:urlRequest];// 加載頁面

}

#pragma mark - UIWebViewDelegate#pragma mark 開始加載網頁

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

? ? ? ?NSLog(@"%@", NSStringFromSelector(_cmd));

}

#pragma mark 網頁加載完成

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

? ? ? NSLog(@"%@", NSStringFromSelector(_cmd));

}

#pragma mark 網頁加載出錯

- (void)webView:(UIWebView*)webView didFailLoadWithError:(nullableNSError*)error {

? ? ? ? NSLog(@"%@:%@", NSStringFromSelector(_cmd), error.localizedDescription);

}

#pragma mark 網頁監聽

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

? ? ? ? NSLog(@"%@", NSStringFromSelector(_cmd));returnYES;

}

@end

運行后你會看到如下的輸出,也體現了三種回調的順序。如果你看到了其他輸出信息,我想你可能出錯了,請查閱前面的介紹,修改后再運行。

webView:shouldStartLoadWithRequest:navigationType:

webViewDidStartLoad:

webViewDidFinishLoad:

4 JS和OC互動

js和oc互動是一件很麻煩的事,畢竟是兩種不同的開發語言。oc調js很簡單,js回調oc就比較麻煩了。

oc調js:uiwebview就自帶這樣的方法

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

js掉oc:我們都知道js可以控制頁面的跳轉,我們還可以在鏈接中攜帶參數。而UIWebView又支持攔截這些請求的操作,這就讓我們完美的實現了js調oc的操作。至于更高級的方法,我們在以后給大家介紹。

改變原有頁面的功能,我們要實現下列需求。

在輸入框輸入相關信息,點擊按鈕,將輸入的信息傳輸到oc中;

oc接受到信息后,通過oc調用js的功能將信息發到js;

js收到信息后,在頁面顯示相關信息。

由于js調用oc是通過url請求發送消息,所以,我們需要制定規范。只有符合我們規范的請求才會執行oc方法,否則不執行。

這里我使用的規范是ios::oc方法名::攜帶的參數。這樣我們在oc端,當發現這樣的請求時就開始攔截執行我們的操作。

我這里的三個參數,相信大家都能看懂,我是使用“::”分割,你也可以使用其他方式分割,或者組合你喜歡的規范。

接下來就是改造oc和js了。在BaseVC添加oc接受js調用的方法體,和改寫- (BOOL)webView:(UIWebView*)webView shouldStartLoadWithRequest:(NSURLRequest*)request navigationType:(UIWebViewNavigationType)navigationType


#pragma mark - js調OC

- (void)jsCallOC:(NSString*)params {

? ? ? ? ? ? ? ?NSLog(@"%@:%@", NSStringFromSelector(_cmd), params);NSString*jsStr = [NSStringstringWithFormat:@"ocCallJS('%@')", params];

// oc調js

[self.webViewstringByEvaluatingJavaScriptFromString:jsStr];

}

#pragma mark 網頁監聽

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

? ? ? ? ? NSLog(@"%@", NSStringFromSelector(_cmd));

? ? ? // 過濾

? ? ?NSString*requestString = request.URL.absoluteString.stringByRemovingPercentEncoding;

? ? ?// 分割

? ? ? NSArray*urlComps = [requestString componentsSeparatedByString:@"::"];

if ( [urlComps count] ==3&& [@"ios"isEqualToString:[urlComps objectAtIndex:0]] ) {

? ? ? ? ? ? ? ?//解析約定的指令

? ? ? ? ? ? ? ?// 方法名

? ? ? ? ? ? ? NSString*methods = [NSStringstringWithFormat:@"%@:", [urlComps objectAtIndex:1]];

? ? ? ? ? ? ? ?SEL selector = NSSelectorFromString(methods);

? ? ? ? ? ? ? ?// 判斷類是否有方法

? ? ? ? ? ? ? ?if ( [BaseVC instancesRespondToSelector:selector]) {

? ? ? ? ? ? ? ? ? ? ? ? ? // 攜帶的參數

? ? ? ? ? ? ? ? ? ? ? NSString*params = [urlComps objectAtIndex:2];

? ? ? ? ? ? ? ? ? ? ? NSLog(@"JS調用OC代碼->UIWebView\n方法名:%@,參數:%@", methods, params);

? ? ? ? ? ? ? ? ? ? ? ? ? ?// 執行方法,攜帶參數

? ? ? ? ? ? ? ? ? ? ? ? ?[selfperformSelector:selector withObject:params];

? ? ? ? ? ? ? ? ?}else{

? ? ? ? ? ? ? ? ? ? ? ? ? ?NSLog(@"沒有提供調用的%@方法名",methods);

? ? ? ? ? ? ? ? ? ?}

? ? ? ? ? ? ? ? ?returnNO;

? ? ? ? ? }

? ? ? ? ?returnYES;

}

[self performSelector:selector withObject:params];這段代碼的意思是執行當前頁面的方法體,并攜帶參數。我們使用通配的方式調用方法體,使代碼更優雅便捷。

然后改變js代碼。


運行項目,然后神奇的事情發生了,原來在app中嵌入網頁這么簡單。

其他

參考資料

UIWebView Class Reference

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 229,836評論 6 540
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 99,275評論 3 428
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 177,904評論 0 383
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,633評論 1 317
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,368評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,736評論 1 328
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,740評論 3 446
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,919評論 0 289
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,481評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 41,235評論 3 358
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,427評論 1 374
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,968評論 5 363
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,656評論 3 348
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,055評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,348評論 1 294
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,160評論 3 398
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,380評論 2 379

推薦閱讀更多精彩內容

  • http://www.cnblogs.com/mddblog/p/5281748.html 一、整體介紹 UIWe...
    F麥子閱讀 1,248評論 0 2
  • 一、簡介 近兩年隨著HTML5的迅速發展與日趨成熟,越來越多的移動開發者選擇使用HTML5來進行混合開發,不僅節約...
    RainyGY閱讀 1,888評論 1 12
  • 前言 關于UIWebView的介紹,相信看過上文的小伙伴們,已經大概清楚了吧,如果有問題,歡迎提問。 本文是本系列...
    CoderLF閱讀 9,007評論 2 12
  • 一、簡介 近兩年隨著HTML5的迅速發展與日趨成熟,越來越多的移動開發者選擇使用HTML5來進行混合開發,不...
    寶寶teacher閱讀 2,337評論 3 15
  • IOS之UIWebView的使用 剛接觸IOS開發1年多,現在對于 混合式 移動端開發越來越流行,因為開發成本上、...
    學無止境666閱讀 45,817評論 5 53