iOS UWebView詳解 - ctaodrea
時間?2013-09-06 17:52:00博客園精華區(qū)
原文http://www.cnblogs.com/ctaodream/p/3305931.html
有時在項目中我們需要嵌入一些web相關(guān)的內(nèi)容,這時你就要用到一個叫UIWebView的東西(UIWebView還可以打開一些文件等,如pdf等),在android和iOS中都有這個東西,使用起來也很方便
只要發(fā)送一個request加載web content就行,而且它也支持會退和前進,此外,你還可以通過它與網(wǎng)頁中的js進行交互,下面看詳細講解。
一、先來看看UIWebView的打開文件的功能,具體支持的文件類型如下:
iPhone OS 2.2.1 supports the following document types:
Excel (.xls)
Keynote (.key.zip)
Numbers (.numbers.zip)
Pages (.pages.zip)
PDF (.pdf)
Powerpoint (.ppt)
Word (.doc)
iPhone OS 3.0 supports these additional document types:
Rich Text Format (.rtf)
Rich Text Format Directory (.rtfd.zip)
Keynote '09 (.key)
Numbers '09 (.numbers)
Pages '09 (.pages)
看到了吧,常用的word,execl 、PDF都能打開。加載這些本地數(shù)據(jù)時,你可以使用loadRequest,或者loadData:MIMEType:textEncodingName:baseURL:,代碼如下:
-(void)loadDocument:(NSString*)documentName inView:(UIWebView*)webView
{//這是你要打開的文件的存放路徑,也可以是document目錄下的路徑NSString *path =[[NSBundle mainBundle] pathForResource:documentName ofType:nil];//當路徑在本地時,就用下面的方法換成url,如果在遠程web上,則用//urlWithStringNSURL *url =[NSURL fileURLWithPath:path];
NSURLRequest*request =[NSURLRequest requestWithURL:url];
[webView loadRequest:request];
}
View Code
NSString*thePath= [[NSBundle mainBundle] pathForResource:@"iPhone_User_Guide"ofType:@"pdf"];if(thePath) {
NSData*pdfData=[NSData dataWithContentsOfFile:thePath];
[(UIWebView*)self.view loadData:pdfData MIMEType:@"application/pdf"textEncodingName:@"utf-8"baseURL:nil];
}
View Code
但記住了,如果你要打開的文件很大,那不可使用這種方法打開。
二、當你要加載一些html數(shù)據(jù)時你可以使用loadHTMLString:baseURL:你也可以用上面的方法加載,對于該控件,最大的作用莫非加載網(wǎng)頁了,下面詳細介紹。。。
1.你可以使用它的方法 loadRequest:加載web content, 停止加載則使用stopLoading,當然,你肯定要知道它是否正在加載,此時你可以通過屬性loading進行判斷。
2.如果你允許用戶向前、向后瀏覽網(wǎng)頁歷史紀錄時,你可以使用方法goBack 和 goForward,當然在使用上面的方法前,你可以判斷是否能繼續(xù)向前,或向后,canGoBack、canGoForward.
3.UIWebView還具有內(nèi)容檢測功能,當網(wǎng)頁內(nèi)容中出現(xiàn)了一些手機號碼、網(wǎng)頁鏈接等東西時,它能夠動態(tài)識別,如果你點擊了它能夠識別的東西,則它會進行相應的處理,如:當發(fā)現(xiàn)你點擊的是電話號碼時,則直接撥號,當發(fā)現(xiàn)你點擊的是網(wǎng)址,則打開瀏覽器前往鏈接,但UIWebView默認只會識別電話號碼,不過你可以通過設(shè)置它的 ? ?來dataDetectorTypes屬性來設(shè)置到底支持那種類型的識別,該屬性值可以是下面的這些
UIDataDetectorTypePhoneNumber? =1<<0,? //識別電話號碼UIDataDetectorTypeLink=1<<1, //識別網(wǎng)址,鏈接等UIDataDetectorTypeAddress=1<<2, // 識別地址UIDataDetectorTypeCalendarEvent=1<<3, // 識別時間UIDataDetectorTypeNone=0, //全都不識別UIDataDetectorTypeAll=NSUIntegerMax// 全部識別
你可以用 或"|" 指定識別其中的幾種
4.UIWebView具有和UIScrollView一樣的放大、縮小功能,你只要設(shè)置屬性scalesPageToFit,為YES就可以達到效果,正因為如此,所以你的UIWebView 不能嵌入到UIScrollView中去,一般加載網(wǎng)頁的代碼如下:
[self.myWebView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:@"http://www.apple.com/"]]];注意了:loadRequest的方法本身就是異步的,所以你不必怕影響性能,自己給他再搞個異步。
5.UIWebView 還有個delegate,主要是用來檢測網(wǎng)頁的加載,以及與網(wǎng)頁中的js實現(xiàn)交互等,與js交互的功能很叼吧,但實現(xiàn)起來可是非常簡單,主要是通過它的方法
-?(NSString*)stringByEvaluatingJavaScriptFromString:(NSString*)script
實現(xiàn)的,你傳入的參數(shù),也就是script的js代碼不能超過10M 大。
6.下面是一些代碼,隨便寫的,不是很完善。里面也有注釋
#import"ViewController.h"@interfaceViewController (){
UIWebView*webView;
UIButton*backBtn;
UIButton*forwardBtn;
UIButton*refreshBtn;
NSURLRequest*currentRequest;//加載時是否發(fā)生errorBOOL hasError;
}@end@implementationViewController- (void)viewDidLoad
{
[super viewDidLoad];//Do any additional setup after loading the view, typically from a nib.webView? = [[UIWebView alloc]initWithFrame:CGRectMake(0,0,320,400)];
[self.view addSubview:webView];
webView.scalesPageToFit=YES;
webView.allowsInlineMediaPlayback=YES;
backBtn=[UIButton buttonWithType:UIButtonTypeRoundedRect];
[backBtn setFrame:CGRectMake(10,420,80,30)];
[backBtn setTitle:@"back"forState:UIControlStateNormal];
[backBtn addTarget:self action:@selector(goBack:) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:backBtn];
refreshBtn=[UIButton buttonWithType:UIButtonTypeRoundedRect];
[refreshBtn setFrame:CGRectMake(120,420,80,30)];
[refreshBtn setTitle:@"refresh"forState:UIControlStateNormal];
[refreshBtn addTarget:self action:@selector(refresh:) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:refreshBtn];
forwardBtn=[UIButton buttonWithType:UIButtonTypeRoundedRect];
[forwardBtn setFrame:CGRectMake(230,420,80,30)];
[forwardBtn setTitle:@"forward"forState:UIControlStateNormal];
[forwardBtn addTarget:self action:@selector(goForward:) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:forwardBtn];//請求鏈接currentRequest = [NSURLRequest requestWithURL:[NSURL URLWithString:@"http://www.baidu.com"]];
hasError=NO;//通過監(jiān)聽web view是否能夠向前 或 向后來決定按鈕是否可用,就像AVCaptureDevice那樣,能監(jiān)聽它自己的屬性---adjustFocusing的變化,這樣就知道它是否在進行聚焦,后面發(fā)現(xiàn),它壓根就不允這樣,試想下,如果知道UIWebView能否前進,或后退,然后根據(jù)這個來設(shè)置前進和后退的按鈕是否可用,那多帥啊(當然,我們可以用定時器實現(xiàn)這功能,但總感覺不好),希望以后能這樣。。。[webView addObserver:self forKeyPath:@"canGoBack"options:NSKeyValueObservingOptionNew context:nil];
[webView addObserver:self forKeyPath:@"canGoForward"options:NSKeyValueObservingOptionNew context:nil];
}//在這迷糊了,發(fā)現(xiàn)一直監(jiān)聽不到,不像 AVCaptureDevice那樣,能監(jiān)聽它自己的屬性---adjustFocusing-(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)objectchange:(NSDictionary *)change context:(void*)contex{
NSLog(@"in observeValueForKeyPath");if([keyPath isEqualToString:@"canGoBack"]) {
BOOL canGoBack= [[change objectForKey:NSKeyValueChangeNewKey] isEqualToNumber:[NSNumber numberWithInt:1]];if(canGoBack) {
[backBtn setEnabled:YES];
}else{
[backBtn setEnabled:NO];
}
}else{
BOOL canGoForward= [[change objectForKey:NSKeyValueChangeNewKey] isEqualToNumber:[NSNumber numberWithInt:1]];if(canGoForward) {
[forwardBtn setEnabled:YES];
}else{
[forwardBtn setEnabled:NO];
}
}
}-(void)viewDidAppear:(BOOL)animated{
[super viewDidAppear:animated];//通過監(jiān)聽web view是否能夠向前 或 向后來決定按鈕是否可用,以前做自定義相機的時候能用這種方式監(jiān)聽是否在自動對焦,然后作出相應的處理,//但現(xiàn)在不管怎么試都沒用,報錯顯示不能這樣做,也不知為什么。。。[webView addObserver:self forKeyPath:@"canGoBack"options:NSKeyValueObservingOptionNew|NSKeyValueObservingOptionOld context:nil];
[webView addObserver:self forKeyPath:@"canGoForward"options:NSKeyValueObservingOptionNew|NSKeyValueObservingOptionOld context:nil];
webView.delegate=self;
[webView loadRequest:currentRequest];
}-(void)viewWillDisappear:(BOOL)animated{
[super viewWillDisappear:animated];if(webView.loading) {
[webView stopLoading];
}
webView.delegate=nil;
}- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];//Dispose of any resources that can be recreated.}#pragmamakr -- button event action-(void)goBack:(id)sender{
NSLog(@"in goBack");if(webView.loading) {
[webView stopLoading];
}
[webView goBack];
}-(void)refresh:(id)sender{
NSLog(@"in refresh");if(webView.loading) {
[webView stopLoading];
}//發(fā)生錯誤時則重新加載主頁if(hasError) {
[webView loadRequest:currentRequest];
}else{
[webView reload];
}
}-(void)goForward:(id)sender{
NSLog(@"in goForward");if(webView.loading) {
[webView stopLoading];
}
[webView goForward];
}#pragmamark -- UIWebDelegate- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType{returnYES;
}//當UIWevView開始加載內(nèi)容時調(diào)用- (void)webViewDidStartLoad:(UIWebView *)webView{
NSLog(@"in webViewDidStartLoad");
[UIApplication sharedApplication].networkActivityIndicatorVisible=YES;
}//當UIWevView完成內(nèi)容加載時調(diào)用- (void)webViewDidFinishLoad:(UIWebView *)webView{
NSLog(@"in webViewDidFinishLoad");
[UIApplication sharedApplication].networkActivityIndicatorVisible=NO;//下面是測試 web view和js交互的例子//該方法是把你傳進來的 js 代碼傳入web網(wǎng)頁中,然后返回執(zhí)行的結(jié)果,返回null則為執(zhí)行失敗NSString *title = [webView stringByEvaluatingJavaScriptFromString:@"document.title"];
NSLog(@"title = %@",title);//下面是網(wǎng)上大牛寫的,嵌入一個值的,是要針對指定網(wǎng)頁的[webView stringByEvaluatingJavaScriptFromString:@"var script = document.createElement('script');""script.type = 'text/javascript';""script.text = \"function myFunction() {""var field = document.getElementsByName('q')[0];""field.value='朱祁林';""document.forms[0].submit();""}\";""document.getElementsByTagName('head')[0].appendChild(script);"];
[webView stringByEvaluatingJavaScriptFromString:@"myFunction();"];
}- (void)webView:(UIWebView *)webView didFailLoadWithError:(NSError *)error{
NSLog(@"in didFailLoadWithError");
[UIApplication sharedApplication].networkActivityIndicatorVisible=NO;
[webView loadHTMLString:[NSString stringWithFormat:@"An error occurred:
%@",[error localizedDescription]] baseURL:nil];
hasError=YES;
}@end