IOS開發系列——UIWebView專題

weixin_34326429發表於2016-01-09

UIWebView專題

1初始化

1.1API介面使用

1.1.1loadhtmlstring

iOS: UIWebview loadhtmlstring & Localcss/js/image resources

http://blog.csdn.net/totogogo/article/details/7613790

UIWebView既可以load by url,還可以load html string。即你可以自己generate html string來用webview顯示。load html string典型的應用是:url所對應的web page內容太多,如果只需要部分的html content,那麼可以通過http request獲取url的html content,然後只選取需要的部分,然後通過load html string來顯示。

自己生成的html,有時無法避免要使用local css, js or image(當然你也可以使用url來連結到網上的css/js/image)。

假設在你的ios app裡的resource folder裡已經存放了a webpage.css and a test.js,那麼你生成的html string應該這樣include them

NSString*

htmlHeader=@"

type='text/css'>@import url('webpage.css');

type='text/javascript' charset='utf-8' src='test.js'>";

NSString* htmlBody=@"";

NSString*htmlFooter=@"";

NSString*strHtml=[[NSStringalloc]initWithFormat:@"%@%@%@",htmlHeader,htmlBody,htmlFooter];

[webViewloadHTMLString:strHtmlbaseURL:[NSURLfileURLWithPath: [[NSBundlemainBundle]resourcePath]isDirectory:YES]];

注意:

1.baseURL就是你的resourcefolder path

2.如果把charset='utf-8' src='test.js'>改成

charset='utf-8' src='test.js' />則無法load js(ref link:http://stackoverflow.com/questions/7840127/uiwebview-loadhtmlstring-not-working-in-ios5

3.當你在ios project裡建立js或者把js新增進來後,by default .js檔案預設會被當作程式碼被compiled(你在build project時就會看到warning),因此你需要將.js files從“compile sources” move to

"Copy bundle resources",見下圖


1419656-7d91e78b0cd4a160.png

1.1.2UIWebView載入本地html檔案

UIWebView *webView_=[[UIWebView alloc] initWithFrame:CGRectMake(0, 0, 320,400)];

webView_.delegate=self;

[self.view addSubview:webView_];

NSString *filePath = [[NSBundle

mainBundle]pathForResource:@"創業企業_詳情" ofType:@"html"];

NSString *htmlString = [NSStringstringWithContentsOfFile:filePath encoding:NSUTF8StringEncoding error:nil];

[webView_ loadHTMLString:htmlString baseURL:[NSURL

URLWithString:filePath]];

2與web互動

2.1WebView中使用Ajax

2.1.1實現機制

Hybrid框架下的app,使用的Ajax,需要注意的是UIWebViewDelegate不會監測到Ajax的request,也就是再執行Ajax程式碼時,shouldStartLoadWithReuqest等方法並不會被呼叫。

其解決方法需要Javascript和navtive code一起來做,其基本原理可參考這片文章,其流程是在Javascript handler中每建立Ajax的請求時,需要將這段js存在ajax_handler.js放在app中

vars_ajaxListener=newObject();

s_ajaxListener.tempOpen=XMLHttpRequest.prototype.open;

s_ajaxListener.tempSend=XMLHttpRequest.prototype.send;

s_ajaxListener.callback=function() {

window.location='mpAjaxHandler://'+ this.url;

};


XMLHttpRequest.prototype.open=function(a,b) {

if (!a) vara='';

if (!b) varb='';

s_ajaxListener.tempOpen.apply(this, arguments);

s_ajaxListener.method=a;

s_ajaxListener.url=b;

if (a.toLowerCase() == 'get') {

s_ajaxListener.data=b.split('?');

s_ajaxListener.data=s_ajaxListener.data[1];

}

}


XMLHttpRequest.prototype.send=function(a,b) {

if (!a) vara='';

if (!b) varb='';

s_ajaxListener.tempSend.apply(this, arguments);

if(s_ajaxListener.method.toLowerCase() == 'post')s_ajaxListener.data=a;

s_ajaxListener.callback();

}

其中的"mpAjaxHandler"為自定義的Scheme,用於區別request是否是由Ajax發出的。

2.1.2在App端獲得js

staticNSString*JSHandler;

+ (void)initialize {

JSHandler = [[NSStringstringWithContentsOfURL:[[NSBundlemainBundle]URLForResource:@"ajax_handler"withExtension:@"js"]encoding:NSUTF8StringEncodingerror:nil]retain];

}

載入頁面後,執行這段js

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

[webViewstringByEvaluatingJavaScriptFromString:JSHandler];

}

攔截住Request,不讓webview的URL做出改變

#define CocoaJSHandler          @"mpAjaxHandler"

- (BOOL)webView:(UIWebView*)webViewshouldStartLoadWithRequest:(NSURLRequest*)requestnavigationType:(UIWebViewNavigationType)navigationType {

if([[[requestURL]scheme]isEqual:CocoaJSHandler]) {

NSString*requestedURLString = [[[requestURL]absoluteString]substringFromIndex:[CocoaJSHandlerlength] +3];

NSLog(@"ajax request: %@", requestedURLString);

returnNO;

}


returnYES;

}

2.1.3Ajax相關知識

Ajax作為非同步Javascript廣泛應用在web網站上。下面是一個來自於w3school的簡單使用Ajax的例子:

function loadXMLDoc()

{

var xmlhttp;

var txt,x,i;

if (window.XMLHttpRequest)

{// code for IE7+, Firefox, Chrome, Opera, Safari

xmlhttp=newXMLHttpRequest();

}

else

{// code for IE6, IE5

xmlhttp=newActiveXObject("Microsoft.XMLHTTP");

}

xmlhttp.onreadystatechange=function()

{

if (xmlhttp.readyState==4 &&xmlhttp.status==200)

{

xmlDoc=xmlhttp.responseXML;

txt="";

x=xmlDoc.getElementsByTagName("title");

for (i=0;i;i++)

{

txt=txt+ x[i].childNodes[0].nodeValue + "/>";

}

document.getElementById("myDiv").innerHTML=txt;

}

}

xmlhttp.open("GET","http://www.w3school.com.cn/example/xmle/books.xml",true);

xmlhttp.send();

}

點選button,通過Ajax的方式獲得書單。部分內容參考於stackoverflow

2.1.4UIWebView載入帶有錨點(anchor)的URL時存在的問題及解決辦法

UIWebView載入帶有錨點(anchor)的URL時存在的問題及解決辦法

http://blog.csdn.net/fengbingyang/article/details/7484453

方案一:

最近在使用ios中的UIWebView顯示本地網頁時,遇到如下問題:

UIWebView載入帶有錨點的URL(如"file:///Users/admin/home.html#pos"),程式使用javascript的range.surroundContents方法在網頁中為選中文字建立高亮標籤,當頁面高度超過螢幕高度時,如果頁面頂部和初始載入時的位置不同(進行過滾動),則每次新增高亮,頁面就重新跳到初始載入時的位置,而不是保持當前位置。

在PC瀏覽器上嘗試並沒有出現這種問題,因此猜測是可能是UIWebView自身的原因。經過一番嘗試,摸索出一種解決辦法,具體如下:

在javascript程式碼的結尾部分新增一句location.href="###";

通過這樣的嘗試,成功讓UIWebView不再跳轉到初始載入位置。

PS:如果UIWebView載入的URL不帶錨點,是不會出現上述問題的。

方案二:在shouldStartLoadWithRequest方法中進行url相等判斷,然後對於#號url進行延遲執行loadNavigationTitle的處理:

- (BOOL)webView:(UIWebView*)webView shouldStartLoadWithRequest:(NSURLRequest*)request

navigationType:(UIWebViewNavigationType)navigationType

{

//如果是第一次載入當前介面,不需要做判斷

if([selfcheckUrl:request.URLIsEqualToTargetUrl:_currentUrl]) {

_lastRequest= request;

if([urlStrrangeOfString:@"#"].length>0) {

[selfperformSelector:@selector(loadNavigationTitle)withObject:nilafterDelay:0.5];

}

returnYES;

}

//其他處理程式碼

}

2.2自定義WebView的userAgent

//獲取iOS預設的UserAgent,可以很巧妙地建立一個空的UIWebView來獲取:

NSString *userAgent = [[[UIWebView

alloc] init]

stringByEvaluatingJavaScriptFromString:@"navigator.userAgent"];

//獲取App名稱,我的App有本地化支援,所以是如下的寫法

NSString *appName =

NSLocalizedStringFromTable(@"CFBundleDisplayName",

@"InfoPlist", nil);

//如果不需要本地化的App名稱,可以使用下面這句

//NSString *appName= [[NSBundle mainBundle]infoDictionary][@"CFBundleDisplayName"];

NSString*version = [[NSBundlemainBundle]infoDictionary][@"CFBundleShortVersionString"];

NSString *customUserAgent = [userAgent

stringByAppendingFormat:@" %@/%@",appName, version];

[[NSUserDefaults standardUserDefaults]

registerDefaults:@{@"UserAgent":customUserAgent}];

// ----------隨便寫個測試程式碼,記得設定delegate哦,這只是測試程式碼

UIWebView *webView = [[UIWebView

alloc] init];

webView.delegate = self;

[webView loadRequest:[NSURLRequest

requestWithURL:[NSURL URLWithString:@"http://www.baidu.com/"]]];

-

(void)webViewDidFinishLoad:(UIWebView *)webView

{

NSLog(@"UserAgent = %@",

[webView

stringByEvaluatingJavaScriptFromString:@"navigator.userAgent"]);

}

Xcode 5.1.1iOS 7.1模擬器下得到的結果是:

Mozilla/5.0 (iPhone; CPU iPhone OS 7_1 like Mac OS X)

AppleWebKit/537.51.2 (KHTML, like Gecko)中華瀏覽器/1.2.2

3參考連結

Hybrid--WebView中使用Ajax

http://blog.csdn.net/xunyn/article/details/38389247

UIWebView怎麼攔截到網頁裡面JS發起的Ajax請求

http://bbs.csdn.net/topics/390967549?page=1

iOS UIWebView自定義UserAgent

http://blog.sina.com.cn/s/blog_6db188450102v529.html

相關文章