iOS與H5交互 以及問題記錄

前提:在iOS控制器中加載UIWebView,設置代理,遵守UIWebViewDelegate協議。
這裏寫圖片描述

一、iOS調用JS方法

通過iOS調用JS代碼實現起來比較方便直接調用UIWebView的方法- (nullable NSString )stringByEvaluatingJavaScriptFromString:(NSString )script;

1.查詢標籤

  // 查詢標籤
  NSString *str = @"var word = document.getElementById('word');"                       @"alert(word.innerHTML)";

[webView stringByEvaluatingJavaScriptFromString:str];

2.爲網頁添加標籤:
NSString *str = @”var img = document.createElement(‘img’);”
“img.src = ‘icon5.jpg’;”
“img.width = 300;”
“img.heigth = 100;”
“document.body.appendChild(img);”;
[webView stringByEvaluatingJavaScriptFromString:str];

3.刪除網頁標籤:
// 刪除標籤
NSString *str1 = @”var word = document.getElementById(‘word’);”
@”word.remove();”;
[webView stringByEvaluatingJavaScriptFromString:str1];

4.更改標籤:
// 更改
NSString *str2 = @”var change = document.getElementsByClassName(‘change’)[0];”
“change.innerHTML = ‘hello’;”;
NSString *result = [webView stringByEvaluatingJavaScriptFromString:str2];

HTML端代碼:

  <!DOCTYPE html>
     <html lang="en">
     <head>
            <meta charset="UTF-8">
            <title>iOS和H5交互</title>
     </head>
     <body>
            <p id="word">6666666666</p>
            <ul>
                 <li class="change">111111</li>
                 <li class="haha">222222</li>
                 <li>333333</li>
                 <li>444444</li>
            </ul>
            <input class="name" placeholder="請輸入密碼">
            <button onclick="buttonClick()">提交信息</button>
    <script type="text/javascript">
            alert('這個一個彈框');
    </script>
    </body>
    </html>

二、JS調用iOS方法:

1.第一種方法比較簡單,通過字符串的比對。這種方式iOS端代碼比較簡單,網頁加載完成後後臺需要重新定義網頁url,將移動端需要的參數拼接到url上返回,或者按照和後臺約定好的字段來進行字符串比對以達到調用iOS方法的目的。下面貼代碼。

    oc代碼:(需要實現webView的協議)

     // 攔截協議頭,調取系統攝像頭

     #pragma mark UIWebViewDelegate

     - (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:            (UIWebViewNavigationType)navigationType

    {

        NSString *str = request.URL.absoluteString;

        if ([str containsString:@"wxd://"]) {

             [self getImage];

         }

        return YES;

     }

    - (void)getImage {
if([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypePhotoLibrary]) { //調用相冊
//實例化控制器
UIImagePickerController *picker = [[UIImagePickerController alloc] init];
picker.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;
picker.delegate = self;
// 是否有圖片選取框
picker.allowsEditing = YES;
[self presentViewController:picker animated:YES completion:nil];
}
}

HTML端代碼:

   <!DOCTYPE html>

   <html lang="en">

          <head>

          <meta charset="UTF-8">

          <title>在html中調用oc的方法</title>

          </head>

          <body>

                  <button onclick="getImage()">訪問相冊</button>

          <script type="text/javascript">

                  function getImage(){

                        window.location.href = "wxd://getImage";

                  }

          </script>

          </body>

   </html>

2.第二種方法,JS直接用oc方法名來調用oc方法,類似於安卓.addJavascriptInterface(new JsObject(), “Android”)方法,頭文件需要導入#import

- (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];
}
}

到此這個問題算是解決了。

二、問題二:
當H5界面中嵌套視頻,在用手機橫屏播放視頻,點擊右上角完成按鈕退出播放界面的時候,會出現導航欄上移,與狀態欄重合的bug。如圖:

這裏寫圖片描述
這裏寫圖片描述
這裏寫圖片描述
左圖爲正常進入H5界面的樣子,點擊視頻播放按鈕,進入視頻播放界面,打開手機的豎排方向鎖定,在手機橫屏時候播放器會自動橫屏播放,這時點擊播放起左上角完成按鈕活着右下角全屏按鈕退出播放界面就會出現右圖的bug,導航欄會向上移動,與狀態欄重合。

解決方法:

第一步:在AppDelegate.h中增加一個屬性值,用來設置是否允許橫屏。代碼如下:

#import <UIKit/UIKit.h>



@interface AppDelegate : UIResponder <UIApplicationDelegate>



@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。

發佈了47 篇原創文章 · 獲贊 18 · 訪問量 5萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章