以前的博客寫過使用庫來實現與H5的交互,可是在項目中仍是遇到了一些不得不踩的坑。在這裏將我遇到的問題以及參考網上幾位大神的解決方案列舉出來,若是有更好的辦法,歡迎討論指正。在閱讀本博客前,請參閱我以前的《iOS與H5交互》。 1、問題一:在webView中加載H5界面,webView中的H5一級界面能夠輕鬆實現oc與js方法互調,但若是在H5界面上進入二級界面,二級界面中再使用以前方法來交互就會失效。如圖:左圖爲H5一級界面,右圖爲二級界面。 解決辦法: 第一步:在控制器中聲明兩個變量,isNotFirstLoad用來記錄webView是不是第一次加載網頁;loadCount計數器,用來記錄網頁轉跳次數,作返回處理。 第二步:實現- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType方法,代碼以下: - (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType { // isNotFirstLoad,記錄webView是否第一次加載H5頁面 if (isNotFirstLoad) { CGRect frame = self.webView.frame; [self.webView removeFromSuperview]; [self.animationView removeFromSuperview]; UIWebView *webView = [[UIWebView alloc] initWithFrame:frame]; webView.delegate = self; [self.view addSubview:webView]; [webView loadRequest:request]; self.webView = webView; //首先建立JSContext 對象(此處經過當前webView的鍵獲取到jscontext) JSContext *context = [webView valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"]; //建立JSTestObjext對象,賦值給js的對象 JSTestObjext *test = [JSTestObjext new]; test.delegate = self; context[@"iOS"] = test; isNotFirstLoad = NO; return NO; } isNotFirstLoad = YES; // 計數器,用來記錄網頁轉跳次數,作返回處理 loadCount ++; if (loadCount == 3) { loadCount = 1; } return YES; } 在網頁轉跳二級界面的時候從新建立UIWebView和JSContext對象,將其當成一個新的網頁,再使用JSContext對象來實現交互的時候就不會出現失效的狀況。 第三步:此時在H5二級界面互調方法就不會有問題了,但新的問題又出現了,當點擊返回按鈕的時候如何返回上級界面。這時就要用到申明的loadCount成員變量了。具體代碼寫在自定義返回按鈕的點擊事件中,我在項目中導航欄是自定義的,重寫返回按鈕只需重寫導航欄的leftBarButtonItem。代碼以下: - (void)viewDidLoad { [super viewDidLoad]; self.title = self.webTitle; // 設置導航欄返回按鈕 self.navigationItem.leftBarButtonItem = [UIBarButtonItem itemWithIcon:@"nav_menu_back_02" highlighted:@"nav_menu_back_03" target:self action:@selector(backClick)]; [self createUI]; } 返回按鈕點擊事件代碼以下: /** * 返回按鈕點擊事件 */ - (void)backClick { if (loadCount == 1) { // pop到上級VC [self.navigationController popViewControllerAnimated:YES]; }else{ // 若是計數器爲2,從新加載一級界面的url NSURL *url = [NSURL URLWithString:self.url]; NSURLRequest *request = [NSURLRequest requestWithURL:url]; [self.webView loadRequest:request]; } } 到此這個問題算是解決了。 2、問題二:當H5界面中嵌套視頻,在用手機橫屏播放視頻,點擊右上角完成按鈕退出播放界面的時候,會出現導航欄上移,與狀態欄重合的bug。如圖: 左圖爲正常進入H5界面的樣子,點擊視頻播放按鈕,進入視頻播放界面,打開手機的豎排方向鎖定,在手機橫屏時候播放器會自動橫屏播放,這時點擊播放起左上角完成按鈕活着右下角全屏按鈕退出播放界面就會出現右圖的bug,導航欄會向上移動,與狀態欄重合。 解決方法: 第一步:在AppDelegate.h中增長一個屬性值,用來設置是否容許橫屏。代碼以下: #import @interface AppDelegate : UIResponder @property (strong, nonatomic) UIWindow *window; /*** 是否容許橫屏的標記 */ @property (nonatomic,assign)BOOL allowRotation; @end 在AppDelegate.m中實現- (UIInterfaceOrientationMask)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(nullable UIWindow *)window方法,具體代碼以下: /** * 是否容許橫屏 */ - (UIInterfaceOrientationMask)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(nullable UIWindow *)window{ if (self.allowRotation) { return UIInterfaceOrientationMaskAll; } return UIInterfaceOrientationMaskPortrait; } 第二步:在加載webView的控制器中註冊兩個通知,經過監聽UIWindow是否可見來判斷視頻播放器是否出現。在viewDidLoad中註冊通知,見代碼: // 播放視頻,監聽視頻播放器 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(begainFullScreen) name:UIWindowDidBecomeVisibleNotification object:nil];//進入全屏 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(endFullScreen) name:UIWindowDidBecomeHiddenNotification object:nil];//退出全屏 實現通知方法: - (void)begainFullScreen { AppDelegate *appDelegate = (AppDelegate *)[[UIApplication sharedApplication] delegate]; appDelegate.allowRotation = YES; } /** * 退出全屏 */ - (void)endFullScreen { AppDelegate *appDelegate = (AppDelegate *)[[UIApplication sharedApplication] delegate]; appDelegate.allowRotation = NO; // 設置設備方向爲豎排 if ([[UIDevice currentDevice] respondsToSelector:@selector(setOrientation:)]) { SEL selector = NSSelectorFromString(@"setOrientation:"); NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:[UIDevice instanceMethodSignatureForSelector:selector]]; [invocation setSelector:selector]; [invocation setTarget:[UIDevice currentDevice]]; int val = UIInterfaceOrientationPortrait; [invocation setArgument:&val atIndex:2]; [invocation invoke]; } } 獲取appDelegate須要引入頭文件#import "AppDelegate.h"。這樣就能夠避免導航欄上移出現的bug。