2013年6月11日 星期二

UIWebView

基本用法
NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"xxxxxxx"]];
UIWebView *webView = [UIWebView alloc] initWithFrame:<#(CGRect)#>];
[webView loadRequest:request];

Tips:
  • Clear Cookies
NSHTTPCookieStorage *storage = [NSHTTPCookieStorage sharedHTTPCookieStorage];
for (NSHTTPCookie *cookie in [storage cookies]) {
[storage deleteCookie:cookie];
}
  • 套用Local Html 及 Local CSS
[webView loadRequest:
  [NSURLRequest requestWithURL:
   [NSURL fileURLWithPath:
    [[NSBundle mainBundle] pathForResource:sourceStr ofType:@"html"]
    ]]];
sourceStr為html file的檔名, 例如main.html, 即為main
而當編譯完成之後打開App來看, 會看到他把所有東西都丟在根目錄下, 不管是Xcode的虛擬資料夾或是檔案目錄下的實體資料夾
故不管圖片路徑或是在html中讀取外部css的路徑等等, 都需使用根目錄路徑

  • 返回上一頁WebView釋放
在WebView還在讀取時若要將webView釋放(例如Navigation返回上一頁), 要在釋放前將讀取動作取消
if (_webView.loading) {
 [_webView stopLoading];
}
_webView.delegate = nil;
否則在 webViewDidFinishLoad 返回時會找不到然後crash
(這似乎只會發生在用Xcode build&run程式做測試才會當掉, 若改成App裝到機器之後stop拔掉連接線 點icon啟動, 怎樣測都測不出來, 聽人說是因為在debug mode關係)

  • https未認證連線
2013/7/22
UIWebView在https為未認證的情況下它會拋出錯誤fail, 要自己處理
而網路上可以找到不少做法是直接忽略(或是可以說直接accept all)所有的認證
不過這做法通常在該文章後面都會附加說明, 此法法僅用於開發用途
用於要上架的App會被reject

我自己弄了個作法, 雖然不知道流程是不是正確, 仿造一般瀏覽器作法詢問使用者
此連線未經過認證, 要不要繼續之類的

在發生webView:didFailLoadWithError:之後 先判斷錯誤類型是不是認證不合法
Error Domain=NSURLErrorDomain Code=-1202 "The certificate for this server is invalid.

之後一樣在fail地方判斷好之後插入個UIAlertView, 設定delegate=self;
- (void)webView:(UIWebView *)webView didFailLoadWithError:(NSError *)error {
 NSLog(@"webView didFailLoadWithError");
 NSLog(@"%@", error);
 
 _failedRequest = webView.request;
 UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"此網站憑證無效" message:@"您仍要繼續連接該網站嗎" delegate:self cancelButtonTitle:@"取消" otherButtonTitles:@"繼續", nil];
 [alertView show];
}

#pragma UIAlertViewDelegate
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex {
 switch (buttonIndex) {
  case 0:
   break;
  case 1: {
   NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"這裡是那個有問題https的網址"]];
   [NSURLConnection connectionWithRequest:request delegate:self];
   break;
  }
 }
}

然後加上NSURLConnectionDelegate
#pragma NSURLConnectionDelegate
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error {
 NSLog(@"%@", NSStringFromSelector(_cmd));
 NSLog(@"%@", error);
}
- (BOOL)connectionShouldUseCredentialStorage:(NSURLConnection *)connection {
 NSLog(@"%@", NSStringFromSelector(_cmd));
    return NO;
}
- (void)connection:(NSURLConnection *)connection willSendRequestForAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge {
 NSLog(@"%@", NSStringFromSelector(_cmd));
 if ([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust]) {
  [challenge.sender useCredential:[NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust] forAuthenticationChallenge:challenge];
 }
}

-(void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response{
 NSLog(@"%@", NSStringFromSelector(_cmd));
 
 [connection cancel];
 connection=nil;
 
 [self.myWebView loadRequest:_failedRequest];
}
這邊比較關鍵的方法是這個 connection:willSendRequestForAuthenticationChallenge:
這邊是給你將該網站加入使用名單中, 然後再加入之後connection:didReceiveResponse得到伺服器回應
再將原本webView讀失敗的網頁重新發request一次

網路上可以找到很多的教學文章都是用這三個方法
// Deprecated authentication delegates.
- (BOOL)connection:(NSURLConnection *)connection canAuthenticateAgainstProtectionSpace:(NSURLProtectionSpace *)protectionSpace;
- (void)connection:(NSURLConnection *)connection didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge;
- (void)connection:(NSURLConnection *)connection didCancelAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge;
不過可看到這幾個是Deprecated
connection:canAuthenticateAgainstProtectionSpace:
connection:didReciveAuthenticationChallenge:
connection:didCancelAuthenticationChallenge:
are deprected and new code should adopt
connection:willSendRequestForAuthenticationChallenge.
The older delegates will still be called for compatability, but incur more latency in dealing with the authentication challenge.
所以竟量別再用了


2013/9/2
又去研究了一下載入CSS以及HTML相關, 看到這篇
這做法可以讓拉近專案的Resources會包含其實體資料夾 而不是把Resources全部都丟在根目錄底下
圖右邊顯示的資料夾內容, 是把 xxx.app右鍵顯示套件內容, 可以看到就包含資料夾

沒有留言:

張貼留言