作業目標:http://www.youtube.com/watch?v=azplcMbuoQ4&feature=youtu.be
練習檔案:homework0831
先介紹一下UIWebView
UIWebView
的資料來源主要有三者:
- 本機上的HTML字串
- 本機上的資料 + MIME type
- 遠端的URL
這邊有中文的介紹:http://www.inside.com.tw/2010/03/14/cs193p-lecture-12
作業練習開始
然後我練習使用程式去產生UINavigationController,這是在AppDelegate.m裡
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { UINavigationController * navi = [UINavigationController new]; UIStoryboard * storyboard = [UIStoryboard storyboardWithName:@"MainStoryboard" bundle:nil]; UIViewController * controller = [storyboard instantiateViewControllerWithIdentifier:@"pink"]; [navi pushViewController:controller animated:YES]; self.window.rootViewController = navi; return YES; }
然後ViewController.h裡在viewDidLoad時初始化一些頁面數值
- (void)viewDidLoad { [super viewDidLoad]; [self.inputURL setAdjustsFontSizeToFitWidth:YES];//設定下方網址列的大小會自動resize self.title = @"填入網址"; self.inputURL.text = @"http://www.apple.com"; }
實作按鈕按下時的動作
- (IBAction)goWeb:(id)sender { //取出webview的view UIStoryboard * storyboard = [UIStoryboard storyboardWithName:@"MainStoryboard" bundle:nil]; WebViewController * webView = [storyboard instantiateViewControllerWithIdentifier:@"webView"]; webView.urlString = self.inputURL.text; webView.delegate = self; [self.inputURL resignFirstResponder];//收起鍵盤 [self.navigationController pushViewController:webView animated:YES]; }
接下來做WebViewController.m裡的內容,
在這邊我弄了一個下載進度的物件叫作UIActivityIndicatorView
這部份首先要先在- (void)viewDidLoad
裡初始化載入效果
//加入載入特效 aciv = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray]; colorView=[[UIView alloc]initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height)]; [colorView setBackgroundColor:[UIColor colorWithRed:0.2 green:0.2 blue:0.2 alpha:0.4]];
然後加上下面兩段程式碼
//載入特效 - (void)addLoading{ aciv.activityIndicatorViewStyle=UIActivityIndicatorViewStyleWhite; aciv.center=CGPointMake(self.view.frame.size.width/2,self.view.frame.size.height/2-10); [self.view addSubview:colorView]; [aciv startAnimating]; [self.view addSubview:aciv]; } - (void)removeLoading{ [colorView removeFromSuperview]; [aciv stopAnimating]; [aciv removeFromSuperview]; }
然後在實做UIWebView的Delegate去設定載入畫面
[UIApplication sharedApplication].networkActivityIndicatorVisible
這個是在上方指示列的圈圈圖示
- (void)webViewDidStartLoad:(UIWebView *)webView { [UIApplication sharedApplication].networkActivityIndicatorVisible = YES; [self addLoading]; } - (void)webViewDidFinishLoad:(UIWebView *)webView { [UIApplication sharedApplication].networkActivityIndicatorVisible = NO; [self removeLoading]; }
遇到問題(高手幫忙看3Q)
然後其實接下來這一點問題我弄了非常久~ 就是,在從上一頁傳來網址時,
也會執行到
-(BOOL) webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType
所以會必須去判斷現在是使用者點擊的link,或是是從上頁傳來的指令
為了這個需求,我用了幾個方式,但都有問題,包括現在的其實也有,但因為實在搞太久~
所以就先這樣@@等老師公布他的作法後再來補修正
我總用試了這些方式
- 使用一個BOOL去判別,只有第一次loading頁面時不做跳頁呼叫,然後當
webViewDidFinishLoad
時將BOOL改為NO
問題點:有某些頁面會有js檔案,當頁面全部載入完成後,執行js後,就又會再第二次讀取網路資料,此時頁面就會莫名的突然回到第一頁然後顯示網址。(例如:我的部落格http://claire-chang.com)
- 使用
NSConnection
(http://stackoverflow.com/questions/9475768/loading-nsdata-into-a-uiwebview)
這是一個異想天開(?)的想法,我想說,第一次loading時用NSConnection
去讀html,然後用loadHTMLString:baseURL:
來顯示在畫面上。結果html成功的載下來了,但是不知為何WebView呈現一片空白。
在網路上查了一下,似乎是因為<scripe>標籤的關係(不確定) - 現在版本的方式:偵測使用者點擊事件,當使用者點擊時,判斷現在是使用者點擊事件,下一次的網頁讀取便會跳頁。
不過這種方式也有問題,同第一點,不過狀況會變成若頁面尚未載入完,使用者就點擊非link的地方時,js呼叫讀取網頁時,就會跳回第一頁,然後網址顯示為js呼叫的頁面網址= =
也是因為這樣子,我才會去製作下載畫面,想說在未loading完前不讓使用者按下WebView,
結果因為畫面會先loading完成、然後才自動因js而去呼叫另一個網址。
中間還是會有使用者可以點擊畫面的時間點。
我總覺得UIWebView應該有個東西是可以直接判別是否是使用者呼叫的,
觀察過dataDetectorTypes的值,卻似乎不是~orz
有知道的人麻煩幫解惑吧~3Q!
ps:若想試有js會在loading完成後再次loading的狀況,請把網址設為我的部落格http://claire-chang.com
因為我是用第三種方式,所以我對WebView增加了碰觸事件的偵聽
首先在- (void)viewDidLoad
設定碰觸事件監聽
//設定碰觸事件 UILongPressGestureRecognizer *longPress = [[UILongPressGestureRecognizer alloc]initWithTarget:self action:@selector(handleTapFrom:)]; longPress.minimumPressDuration = .001; longPress.delegate = self; [self.web addGestureRecognizer:longPress]; [self.web addGestureRecognizer:test];
然後要實作UIGestureRecognizerDelegate
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer { return YES; }
上面這個一定要加,這樣子handleTapFrom:
才會被呼叫到
然後當按到時將bool值改成YES
-(void)handleTapFrom :(UITapGestureRecognizer *)sender{ NSLog(@"handleTapFrom:%d",sender.state); isClick = YES; }
當讀取網頁且isClick是YES時就跳回第一頁
-(BOOL) webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType{ if(isClick){ [self.delegate userClickWebLink:request.URL.absoluteString]; return NO; } return YES; }
這時再回去ViewController.m增加接收的方法
-(void) userClickWebLink: (NSString *) url{ [self.navigationController popViewControllerAnimated:YES]; self.title = @"點選網址"; self.webUrl.text = url; }