iOS開發(fā):給UIWebview的導(dǎo)航欄添加返回深夯、關(guān)閉按鈕

在我們平日的開發(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)閉按鈕:

圖片1.png

圖片2.png

圖片3.png

GitHub地址:Demo
純手打篇裁,喜歡點(diǎn)個贊,希望對看到的你有所幫助I娜簟4锊肌!

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末逾冬,一起剝皮案震驚了整個濱河市黍聂,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌身腻,老刑警劉巖产还,帶你破解...
    沈念sama閱讀 216,324評論 6 498
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異嘀趟,居然都是意外死亡脐区,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,356評論 3 392
  • 文/潘曉璐 我一進(jìn)店門她按,熙熙樓的掌柜王于貴愁眉苦臉地迎上來牛隅,“玉大人炕柔,你說我怎么就攤上這事【蟮穑” “怎么了汗唱?”我有些...
    開封第一講書人閱讀 162,328評論 0 353
  • 文/不壞的土叔 我叫張陵宫莱,是天一觀的道長丈攒。 經(jīng)常有香客問我,道長授霸,這世上最難降的妖魔是什么巡验? 我笑而不...
    開封第一講書人閱讀 58,147評論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮碘耳,結(jié)果婚禮上显设,老公的妹妹穿的比我還像新娘。我一直安慰自己辛辨,他們只是感情好捕捂,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,160評論 6 388
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著斗搞,像睡著了一般指攒。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上僻焚,一...
    開封第一講書人閱讀 51,115評論 1 296
  • 那天允悦,我揣著相機(jī)與錄音,去河邊找鬼虑啤。 笑死隙弛,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的狞山。 我是一名探鬼主播全闷,決...
    沈念sama閱讀 40,025評論 3 417
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼萍启!你這毒婦竟也來了室埋?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,867評論 0 274
  • 序言:老撾萬榮一對情侶失蹤伊约,失蹤者是張志新(化名)和其女友劉穎姚淆,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體屡律,經(jīng)...
    沈念sama閱讀 45,307評論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡腌逢,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,528評論 2 332
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了超埋。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片搏讶。...
    茶點(diǎn)故事閱讀 39,688評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡佳鳖,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出媒惕,到底是詐尸還是另有隱情系吩,我是刑警寧澤,帶...
    沈念sama閱讀 35,409評論 5 343
  • 正文 年R本政府宣布妒蔚,位于F島的核電站穿挨,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏肴盏。R本人自食惡果不足惜科盛,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,001評論 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望菜皂。 院中可真熱鬧贞绵,春花似錦、人聲如沸恍飘。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,657評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽章母。三九已至母蛛,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間胳施,已是汗流浹背溯祸。 一陣腳步聲響...
    開封第一講書人閱讀 32,811評論 1 268
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留舞肆,地道東北人焦辅。 一個月前我還...
    沈念sama閱讀 47,685評論 2 368
  • 正文 我出身青樓,卻偏偏與公主長得像椿胯,于是被迫代替她去往敵國和親筷登。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,573評論 2 353

推薦閱讀更多精彩內(nèi)容