http://blog.csdn.net/y550918116j/article/details/49619847
當你在項目中想嵌入網(wǎng)頁時森书,可以使用UIWebView類嵌入Web內(nèi)容。你只需要創(chuàng)建一個UIWebView對象谎势,并將它附加到一個view窗口凛膏。你還可以使用這個類來執(zhí)行頁面歷史的前進或后退。
本文主要介紹關(guān)于UIWebView的基礎脏榆,包括:加載網(wǎng)頁猖毫、實現(xiàn)代理以及JS和OC的互相調(diào)用。
1 準備工作
我已經(jīng)為大家創(chuàng)建了html頁面的源代碼须喂,只需要復制到記事本吁断,并將文件名改為index.html趁蕊。
這個頁面有輸入框、按鈕和做顯示用的仔役,其簡單功能是在輸入框輸入數(shù)據(jù)掷伙,點擊按鈕后顯示到顯示區(qū)域。
在瀏覽器運行可以看到如下效果又兵。
1.2 搭建項目
這個地方就不詳細描述了任柜,創(chuàng)建一個簡單項目->拉一個UIWebView到界面->UIWebView指向UIViewController的屬性名。
搭建后的核心部分如下沛厨,這里我使用的VC名為BaseVC宙地。
#import"BaseVC.h"@interfaceBaseVC() @property(weak,nonatomic)IBOutletUIWebView*webView;///< UIWebView
@end@implementationBaseVC
- (void)viewDidLoad {
[superviewDidLoad];
}@end
2 顯示W(wǎng)eb頁面
將我們創(chuàng)建好的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]去尋找页屠。如果你使用的是網(wǎng)咯連接“www.baidu.com”,你可以這樣獲得NSURL。
url =[NSURL URLWithString:@"www.baidu.com"];
然后運行項目蓖柔,就可以看到和瀏覽器一樣的效果辰企。
3 代理UIWebViewDelegate
UIWebView也有代理,如果你不懂什么是代理模式况鸣,查閱我的博文《23設計模式之代理模式(Proxy)》牢贸。我們在UIWebViewDelegate發(fā)現(xiàn)了四個方法。
__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代表繼續(xù)加載潜索,no代表不加載。
- (void)webViewDidStartLoad:(UIWebView *)webView;:
開始加載web頁面懂酱;
- (void)webViewDidFinishLoad:(UIWebView *)webView;:
加載web頁面結(jié)束;
- (void)webView:(UIWebView *)webView didFailLoadWithError:(nullable NSError *)error;:
加載web頁面出錯竹习,你可以在error看到錯誤信息。
現(xiàn)在我們改造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 開始加載網(wǎng)頁
- (void)webViewDidStartLoad:(UIWebView*)webView {
? ? ? ?NSLog(@"%@", NSStringFromSelector(_cmd));
}
#pragma mark 網(wǎng)頁加載完成
- (void)webViewDidFinishLoad:(UIWebView*)webView {
? ? ? NSLog(@"%@", NSStringFromSelector(_cmd));
}
#pragma mark 網(wǎng)頁加載出錯
- (void)webView:(UIWebView*)webView didFailLoadWithError:(nullableNSError*)error {
? ? ? ? NSLog(@"%@:%@", NSStringFromSelector(_cmd), error.localizedDescription);
}
#pragma mark 網(wǎng)頁監(jiān)聽
- (BOOL)webView:(UIWebView*)webView shouldStartLoadWithRequest:(NSURLRequest*)request navigationType:(UIWebViewNavigationType)navigationType {
? ? ? ? NSLog(@"%@", NSStringFromSelector(_cmd));returnYES;
}
@end
運行后你會看到如下的輸出,也體現(xiàn)了三種回調(diào)的順序瞎领。如果你看到了其他輸出信息泌辫,我想你可能出錯了,請查閱前面的介紹九默,修改后再運行震放。
webView:shouldStartLoadWithRequest:navigationType:
webViewDidStartLoad:
webViewDidFinishLoad:
4 JS和OC互動
js和oc互動是一件很麻煩的事,畢竟是兩種不同的開發(fā)語言驼修。oc調(diào)js很簡單澜搅,js回調(diào)oc就比較麻煩了伍俘。
oc調(diào)js:uiwebview就自帶這樣的方法
- (nullable NSString *)stringByEvaluatingJavaScriptFromString:(NSString *)script;
js掉oc:我們都知道js可以控制頁面的跳轉(zhuǎn),我們還可以在鏈接中攜帶參數(shù)勉躺。而UIWebView又支持攔截這些請求的操作癌瘾,這就讓我們完美的實現(xiàn)了js調(diào)oc的操作。至于更高級的方法饵溅,我們在以后給大家介紹妨退。
改變原有頁面的功能,我們要實現(xiàn)下列需求蜕企。
在輸入框輸入相關(guān)信息咬荷,點擊按鈕,將輸入的信息傳輸?shù)給c中轻掩;
oc接受到信息后幸乒,通過oc調(diào)用js的功能將信息發(fā)到js;
js收到信息后唇牧,在頁面顯示相關(guān)信息罕扎。
由于js調(diào)用oc是通過url請求發(fā)送消息,所以丐重,我們需要制定規(guī)范腔召。只有符合我們規(guī)范的請求才會執(zhí)行oc方法,否則不執(zhí)行扮惦。
這里我使用的規(guī)范是ios::oc方法名::攜帶的參數(shù)臀蛛。這樣我們在oc端,當發(fā)現(xiàn)這樣的請求時就開始攔截執(zhí)行我們的操作崖蜜。
我這里的三個參數(shù)浊仆,相信大家都能看懂,我是使用“::”分割豫领,你也可以使用其他方式分割氧卧,或者組合你喜歡的規(guī)范。
接下來就是改造oc和js了氏堤。在BaseVC添加oc接受js調(diào)用的方法體沙绝,和改寫- (BOOL)webView:(UIWebView*)webView shouldStartLoadWithRequest:(NSURLRequest*)request navigationType:(UIWebViewNavigationType)navigationType
#pragma mark - js調(diào)OC
- (void)jsCallOC:(NSString*)params {
? ? ? ? ? ? ? ?NSLog(@"%@:%@", NSStringFromSelector(_cmd), params);NSString*jsStr = [NSStringstringWithFormat:@"ocCallJS('%@')", params];
// oc調(diào)js
[self.webViewstringByEvaluatingJavaScriptFromString:jsStr];
}
#pragma mark 網(wǎng)頁監(jiān)聽
- (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]) {
? ? ? ? ? ? ? ? ? ? ? ? ? // 攜帶的參數(shù)
? ? ? ? ? ? ? ? ? ? ? NSString*params = [urlComps objectAtIndex:2];
? ? ? ? ? ? ? ? ? ? ? NSLog(@"JS調(diào)用OC代碼->UIWebView\n方法名:%@,參數(shù):%@", methods, params);
? ? ? ? ? ? ? ? ? ? ? ? ? ?// 執(zhí)行方法,攜帶參數(shù)
? ? ? ? ? ? ? ? ? ? ? ? ?[selfperformSelector:selector withObject:params];
? ? ? ? ? ? ? ? ?}else{
? ? ? ? ? ? ? ? ? ? ? ? ? ?NSLog(@"沒有提供調(diào)用的%@方法名",methods);
? ? ? ? ? ? ? ? ? ?}
? ? ? ? ? ? ? ? ?returnNO;
? ? ? ? ? }
? ? ? ? ?returnYES;
}
[self performSelector:selector withObject:params];這段代碼的意思是執(zhí)行當前頁面的方法體鼠锈,并攜帶參數(shù)闪檬。我們使用通配的方式調(diào)用方法體,使代碼更優(yōu)雅便捷购笆。
然后改變js代碼粗悯。
運行項目,然后神奇的事情發(fā)生了同欠,原來在app中嵌入網(wǎng)頁這么簡單样傍。