WebView和H5的那點事

Sheffi發表於2016-11-23

在iOS開發中好多時候,原生的app會很大的限制,也會有好多難以實現的東西。那就需要與H5進行混合開發,那就使用到了webView。
一、首先簡單介紹一下webView:
1、三種載入方式:

- (void)loadRequest:(NSURLRequest *)request;//這是載入網頁最常用的一種方式,通過一個網頁URL來進行載入,這個URL可以是遠端的也可以是本地的
- (void)loadHTMLString:(NSString *)string baseURL:(nullable NSURL *)baseURL;//這個方法需要將httml檔案讀取為字串,其中baseURL是我們自己設定的一個路徑,用於尋找html檔案中引用的圖片等素材。
- (void)loadData:(NSData *)data MIMEType:(NSString *)MIMEType textEncodingName:(NSString *)textEncodingName baseURL:(NSURL *)baseURL;//這個方式使用的比較少,但也更加自由,其中data是檔案資料,MIMEType是檔案型別,textEncodingName是編碼型別,baseURL是素材資源路徑。複製程式碼

2、一些常用的屬性和變數

@property (nonatomic,assign)id  delegate;//設定webView的代理

@property (nonatomic,readonly,retain)UIScrollView *scrollView;//內建的scrollView

@property (nonatomic,readonly,retain)NSURLRequest *request;//URL請求

- (void)reload;//重新載入資料

- (void)stopLoading;//停止載入資料

- (void)goBack;//返回上一級

- (void)goForward;//跳轉下一級

@property (nonatomic,readonly,getter=canGoBack)BOOL canGoBack;//獲取能否返回上一級

@property (nonatomic,readonly,getter=canGoForward)BOOL canGoForward;//獲取能否跳轉下一級

@property (nonatomic,readonly,getter=isLoading)BOOL loading;//獲取是否正在載入資料

- (NSString *)stringByEvaluatingJavaScriptFromString:(NSString *)script;//通過JavaScript操作web資料

@property (nonatomic)BOOL scalesPageToFit;//設定是否縮放到適合螢幕大小

@property (nonatomic)UIDataDetectorTypes dataDetectorTypesNS_AVAILABLE_IOS(3_0);//設定某些資料變為連結形式,這個列舉可以設定如電話號,地址,郵箱等轉化為連結

@property (nonatomic)BOOL allowsInlineMediaPlaybackNS_AVAILABLE_IOS(4_0);//設定是否使用內聯播放器播放視訊

@property (nonatomic)BOOL mediaPlaybackRequiresUserActionNS_AVAILABLE_IOS(4_0);//設定視訊是否自動播放

@property (nonatomic)BOOL mediaPlaybackAllowsAirPlayNS_AVAILABLE_IOS(5_0);//設定音訊播放是否支援ari play功能

@property (nonatomic)BOOL suppressesIncrementalRenderingNS_AVAILABLE_IOS(6_0);//設定是否將資料載入如記憶體後渲染介面

@property (nonatomic)BOOL keyboardDisplayRequiresUserActionNS_AVAILABLE_IOS(6_0);//設定使用者互動模式複製程式碼
@property (nonatomic)UIWebPaginationMode paginationModeNS_AVAILABLE_IOS(7_0);

    typedef NS_ENUM(NSInteger, UIWebPaginationMode) {
        UIWebPaginationModeUnpaginated,//不使用翻頁效果
        UIWebPaginationModeLeftToRight,//將網頁超出部分分頁,從左向右進行翻頁
        UIWebPaginationModeTopToBottom,//將網頁超出部分分頁,從上向下進行翻頁
        UIWebPaginationModeBottomToTop,//將網頁超出部分分頁,從下向上進行翻頁
        UIWebPaginationModeRightToLeft//將網頁超出部分分頁,從右向左進行翻頁
    };

//這個屬性用來設定一種模式,當網頁的大小超出view時,將網頁以翻頁的效果展示,列舉如下:

@property (nonatomic)CGFloat pageLengthNS_AVAILABLE_IOS(7_0);//設定每一頁的長度

@property (nonatomic)CGFloat gapBetweenPagesNS_AVAILABLE_IOS(7_0);//設定每一頁的間距

@property (nonatomic,readonly)NSUInteger pageCountNS_AVAILABLE_IOS(7_0);//獲取分頁數複製程式碼

3、webView協議中的方法

- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType;//準備載入內容時呼叫的方法,通過返回值來進行是否載入的設定

- (void)webViewDidStartLoad:(UIWebView *)webView;//開始載入時呼叫的方法

- (void)webViewDidFinishLoad:(UIWebView *)webView;//結束載入時呼叫的方法

- (void)webView:(UIWebView *)webView didFailLoadWithError:(NSError *)error;//載入失敗時呼叫的方法複製程式碼

以上就是webView的屬性、方法以及代理方法的簡單解釋。
二、簡單給出一個例子:(載入一個京東的介面),直接上程式碼:

 self.webView = [[UIWebView alloc]initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height)];
    self.webView.delegate = self;
    [self.view addSubview:self.webView];
    NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"http://www.jd.com"]];
    [self.webView loadRequest:request];複製程式碼

這裡webView的載入請求,也可以像平時做網路請求一樣進行設定“GET”或“POST”請求,這需要根據後臺的需求。例如一個是用post請求的例子:
注:這裡的HTTP_AFNETWORKING_POST_URLURL_Detail_H5([userManage key], _record_type, _record_id) 都是實際專案中的巨集定義。

    _webView.frame = CGRectMake(0, 0, SCREEN_W, 0);
    _webView.delegate = self;
    NSURL *url = [NSURL URLWithString: HTTP_AFNETWORKING_POST_URL];
    NSString *body = URL_Detail_H5([userManage key], _record_type, _record_id);
    NSMutableURLRequest *request = [[NSMutableURLRequest alloc]initWithURL: url];
    [request setHTTPMethod: @"POST"];
    [request setHTTPBody: [body dataUsingEncoding: NSUTF8StringEncoding]];
    [self.webView loadRequest:request];複製程式碼

三、很多時候,webView載入了H5介面之後,如果H5介面過長,webView能進行滾動,但是有時需要進行讓webView自適應,自適應的方法如下:
在網頁載入完成的時候,使用stringByEvaluatingJavaScriptFromString實現UIWebView與JavaScript之間的互動,很方便的操作UIWebview中的頁面元素。獲取Html的高度。
雖然這個方法能使webView高度為顯示的HTML實際高度,但效果並不是太好,當高度超出螢幕時,無法滾動下拉。但是這種方法與scrollview一起使用可以很好的控制滾動。

-(void)webViewDidFinishLoad:(UIWebView *)webView{
    NSInteger height = [[webView stringByEvaluatingJavaScriptFromString:@"document.body.scrollHeight"] integerValue];
    self.webView.frame=CGRectMake(0, 0, self.view.frame.size.width,height);
}複製程式碼

或者使用監聽:

 [_webView.scrollView addObserver:self forKeyPath:@"contentSize" options:NSKeyValueObservingOptionNew context:nil];

 //監聽
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
{
    if ([keyPath isEqualToString:@"contentSize"]) {
        NSInteger height = [[_webView stringByEvaluatingJavaScriptFromString:@"document.body.scrollHeight"] integerValue];
        self.webView.frame=CGRectMake(0, 0, self.view.frame.size.width,height);
        [self setUILayout];

    }
}複製程式碼

四、最後說與網頁的互動。
很多時候我們需要監聽使用者點選了網頁上的內容我們進行相應的跳轉到原生的介面上,這裡就使用到了webView代理方法中的

- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType複製程式碼

這個方法。網頁中的每一個請求都會被觸發這個方法,返回NO代表不執行這個請求(常用於JS與iOS之間通訊)。
還是以京東首頁為例子,首先load一個京東介面,然後監聽京東介面的京東超市那個請求,當發出這個請求,然後跳轉到我們自己的原生介面。
效果圖:

WebView和H5的那點事
這裡寫圖片描述

WebView和H5的那點事
這裡寫圖片描述

直接上程式碼:

#import "ViewController.h"
#import "aaa.h"

@interface ViewController ()

@property (strong, nonatomic) UIWebView *webView;

@property (strong, nonatomic) UIActivityIndicatorView *activityIndicatorView;

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.
    self.webView = [[UIWebView alloc]initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height)];
    self.webView.delegate = self;
    [self.view addSubview:self.webView];

    NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"http://www.jd.com"]];
    [self.webView loadRequest:request];

    self.activityIndicatorView = [[UIActivityIndicatorView alloc]initWithFrame:CGRectMake(0, 0, 32, 32)];
    self.activityIndicatorView.center = self.view.center;
    [self.activityIndicatorView setActivityIndicatorViewStyle:UIActivityIndicatorViewStyleWhiteLarge];
    [self.view addSubview:self.activityIndicatorView];

}
#pragma mark - **************** delegate
/**
 *  開始載入網頁
 *
 *  @param webView
 */
-(void)webViewDidStartLoad:(UIWebView *)webView{
    NSLog(@"webViewDidStartLoad");
    [self.activityIndicatorView startAnimating];
}
/**
 *  網頁載入完成的時候呼叫
 *
 *  @param webView
 */
-(void)webViewDidFinishLoad:(UIWebView *)webView{
    NSLog(@"webViewDidFinishLoad");
    [self.activityIndicatorView stopAnimating];
}
/**
 *  網頁載入出錯的時候呼叫
 *
 *  @param webView
 *  @param error
 */
-(void)webView:(UIWebView *)webView didFailLoadWithError:(NSError *)error{
    if (error != nil) {
        NSLog(@"%@",[error description]);
    }
    [self.activityIndicatorView stopAnimating];
}
/**
 *   網頁中的每一個請求都會被觸發這個方法,返回NO代表不執行這個請求(常用於JS與iOS之間通訊)
 *
 *  @param webView
 *  @param request
 *  @param navigationType
 *
 *  @return
 */
- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType {
    NSLog(@"ssss%@",request);
    if ([request.URL.absoluteString isEqualToString:@"http://pro.m.jd.com/2hqsQcyM5bEUVSStkN3BwrBHqVLd/index.html"] ) {
        aaa *aa = [[aaa alloc]init];
        [self presentViewController:aa animated:YES completion:nil];
        return NO;
    }
    return YES;
}
- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

@end複製程式碼

以上就是對webView的簡單實用的總結。如有錯誤,請留言指出,將感激不盡。

微信公眾號:不靠譜程式猿 微信公眾號:Sheffi_Programmer
Github:Sheffi(github.com/goingmyway1… 新浪微博:Sheffi567
掘金:Sheffi(gold.xitu.io/user/57c137…

相關文章