在我們平日的開發(fā)中鄙陡,不免有原生與H5的交互喻旷,比如說:從原生頁面的一個按鈕生逸,點(diǎn)擊之后跳轉(zhuǎn)到了一個H5的頁面A,A頁面中又有一個按鈕,點(diǎn)擊之后槽袄,又加載了一個新的H5頁面B烙无,從B點(diǎn)擊一個按鈕,又加載一個新的H5頁面C遍尺,如果此時我們點(diǎn)擊左上角的返回按鈕截酷,會直接返回到我們的原生頁面;
是不是上面給用戶的體驗(yàn)很不好(當(dāng)然殘品經(jīng)理會覺得是乾戏,我們都是無所謂的啦)迂苛,此時我們想要重新定制返回按鈕,我們想要從C頁面判斷是否還有上一級H5頁面可供返回鼓择,如果有上一級頁面還是H5三幻,點(diǎn)擊左上角的返回則返回到B頁面,并且在B頁面的左上角加上一個關(guān)閉按鈕呐能,這個關(guān)閉按鈕的作用主要是為了關(guān)閉所有的H5的頁面念搬,直接返回到我們原生的頁面;如果我們不點(diǎn)擊關(guān)閉按鈕摆出,還是點(diǎn)擊返回朗徊,則從B頁面返回到A頁面;再次點(diǎn)擊返回偎漫,則關(guān)閉了H5的頁面爷恳,回到了原生的頁面;
說的也許有點(diǎn)兒繞象踊,不過大致思想就是:先判斷當(dāng)前的H5頁面是否可以返回:
//判斷當(dāng)前H5是否可以返回
[self.webView canGoBack]
如果可以返回舌仍,則返回到上一個H5頁面,并在左上角添加一個關(guān)閉按鈕通危,如果不可以返回铸豁,則直接:
//回到原生頁面
[self.navigationController popViewControllerAnimated:YES];
下面是我的主要實(shí)現(xiàn)代碼,我寫一個繼承與UIViewController的類菊碟,接受了UIWebviewDelegate节芥,并定義了一個UIwebview的屬性,給外面留了一個方法逆害,只需要傳遞一個URL头镊,我們就可以加載;如果有地方需要加載H5的頁面魄幕,我們可以直接集成與這個類相艇,這樣的好處在于方便維護(hù);
當(dāng)然我封裝的這個類纯陨,同時也是支持HTTPS的請求的坛芽;話不多說留储,代碼如下:
創(chuàng)建一個類,繼承與UIViewController咙轩,.h中的代碼
#import <UIKit/UIKit.h>
@interface SYWebViewController : UIViewController<UIWebViewDelegate, NSURLConnectionDelegate>
//定義一個屬性获讳,方便外接調(diào)用
@property (nonatomic, strong) UIWebView *webView;
//聲明一個方法,外接調(diào)用時活喊,只需要傳遞一個URL即可
- (void)loadHTML:(NSString *)htmlString;
@end
.m中的實(shí)現(xiàn)如下:
#import "SYWebViewController.h"
@interface NSURLRequest (InvalidSSLCertificate)
+ (BOOL)allowsAnyHTTPSCertificateForHost:(NSString*)host;
+ (void)setAllowsAnyHTTPSCertificate:(BOOL)allow forHost:(NSString*)host;
@end
@interface SYWebViewController ()
@property (nonatomic, strong) NSURLRequest *request;
//判斷是否是HTTPS的
@property (nonatomic, assign) BOOL isAuthed;
//返回按鈕
@property (nonatomic, strong) UIBarButtonItem *backItem;
//關(guān)閉按鈕
@property (nonatomic, strong) UIBarButtonItem *closeItem;
@end
@implementation SYWebViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.view.backgroundColor = [UIColor whiteColor];
self.webView = [[UIWebView alloc] initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height - 64)];
[self.view addSubview:self.webView];
[self addLeftButton];
}
//加載URL
- (void)loadHTML:(NSString *)htmlString
{
NSURL *url = [NSURL URLWithString:htmlString];
self.request = [NSURLRequest requestWithURL:url cachePolicy:NSURLRequestReloadIgnoringLocalCacheData timeoutInterval:5.0];
[NSURLRequest setAllowsAnyHTTPSCertificate:YES forHost:[url host]];
[self.webView loadRequest:self.request];
}
#pragma mark - UIWebViewDelegate
//開始加載
- (BOOL)webView:(UIWebView *)awebView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType
{
NSString* scheme = [[request URL] scheme];
//判斷是不是https
if ([scheme isEqualToString:@"https"]) {
//如果是https:的話丐膝,那么就用NSURLConnection來重發(fā)請求。從而在請求的過程當(dāng)中吧要請求的URL做信任處理钾菊。
if (!self.isAuthed) {
NSURLConnection* conn = [[NSURLConnection alloc] initWithRequest:request delegate:self];
[conn start];
[awebView stopLoading];
return NO;
}
}
return YES;
}
//設(shè)置webview的title為導(dǎo)航欄的title
- (void)webViewDidFinishLoad:(UIWebView *)webView
{
self.title = [webView stringByEvaluatingJavaScriptFromString:@"document.title"];
}
#pragma mark ================= NSURLConnectionDataDelegate <NSURLConnectionDelegate>
- (BOOL)connection:(NSURLConnection *)connection canAuthenticateAgainstProtectionSpace:(NSURLProtectionSpace *)protectionSpace
{
return [protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust];
}
- (void)connection:(NSURLConnection *)connection willSendRequestForAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge
{
if ([challenge previousFailureCount] == 0) {
self.isAuthed = YES;
//NSURLCredential 這個類是表示身份驗(yàn)證憑據(jù)不可變對象帅矗。憑證的實(shí)際類型聲明的類的構(gòu)造函數(shù)來確定。
NSURLCredential *cre = [NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust];
[challenge.sender useCredential:cre forAuthenticationChallenge:challenge];
}
}
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error
{
NSLog(@"網(wǎng)絡(luò)不給力");
}
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
{
self.isAuthed = YES;
//webview 重新加載請求煞烫。
[self.webView loadRequest:self.request];
[connection cancel];
}
#pragma mark - 添加關(guān)閉按鈕
- (void)addLeftButton
{
self.navigationItem.leftBarButtonItem = self.backItem;
}
//點(diǎn)擊返回的方法
- (void)backNative
{
//判斷是否有上一層H5頁面
if ([self.webView canGoBack]) {
//如果有則返回
[self.webView goBack];
//同時設(shè)置返回按鈕和關(guān)閉按鈕為導(dǎo)航欄左邊的按鈕
self.navigationItem.leftBarButtonItems = @[self.backItem, self.closeItem];
} else {
[self closeNative];
}
}
//關(guān)閉H5頁面损晤,直接回到原生頁面
- (void)closeNative
{
[self.navigationController popViewControllerAnimated:YES];
}
#pragma mark - init
- (UIBarButtonItem *)backItem
{
if (!_backItem) {
_backItem = [[UIBarButtonItem alloc] init];
UIButton *btn = [UIButton buttonWithType:UIButtonTypeCustom];
//這是一張“<”的圖片,可以讓美工給切一張
UIImage *image = [UIImage imageNamed:@"sy_back"];
[btn setImage:image forState:UIControlStateNormal];
[btn setTitle:@"返回" forState:UIControlStateNormal];
[btn addTarget:self action:@selector(backNative) forControlEvents:UIControlEventTouchUpInside];
[btn.titleLabel setFont:[UIFont systemFontOfSize:17]];
[btn setTitleColor:[UIColor sy_backColor] forState:UIControlStateNormal];
//字體的多少為btn的大小
[btn sizeToFit];
//左對齊
btn.contentHorizontalAlignment = UIControlContentHorizontalAlignmentLeft;
//讓返回按鈕內(nèi)容繼續(xù)向左邊偏移15红竭,如果不設(shè)置的話尤勋,就會發(fā)現(xiàn)返回按鈕離屏幕的左邊的距離有點(diǎn)兒大,不美觀
btn.contentEdgeInsets = UIEdgeInsetsMake(0, -15, 0, 0);
btn.frame = CGRectMake(0, 0, 40, 40);
_backItem.customView = btn;
}
return _backItem;
}
- (UIBarButtonItem *)closeItem
{
if (!_closeItem) {
_closeItem = [[UIBarButtonItem alloc] initWithTitle:@"關(guān)閉" style:UIBarButtonItemStylePlain target:self action:@selector(closeNative)];
}
return _closeItem;
}
@end
具體的使用方法就是茵宪,創(chuàng)建一個類最冰,繼承與這類:SYWebViewController
#import <UIKit/UIKit.h>
#import "SYWebViewController.h"
@interface SYFlashHTMLViewController : SYWebViewController
@end
然后在這個類的.m中的viewDidLoad中,調(diào)用父視圖加載URL的方法稀火,即:
- (void)viewDidLoad {
[super viewDidLoad];
self.webView.delegate = self;
[self loadHTML:self.htmlString];
}
效果如下圖:打開百度(圖片1)暖哨,點(diǎn)擊圖片進(jìn)入(圖片2),點(diǎn)擊返回返回到(圖片3)凰狞,圖片1和圖片的區(qū)別在于多了個關(guān)閉按鈕:
GitHub地址:Demo
純手打篇裁,喜歡點(diǎn)個贊,希望對看到的你有所幫助I娜簟4锊肌!