1. 程式人生 > >WKWebview 呼叫js的方法以及遇到的坑

WKWebview 呼叫js的方法以及遇到的坑

今天做webview和js互動的諸多事宜。
眾所周知wkwebview呼叫js的方法,要呼叫如下程式碼

- (void)evaluateJavaScript:(NSString *)javaScriptString completionHandler:(void (^ _Nullable)(_Nullable id, NSError * _Nullable error))completionHandler;

//例如OC呼叫JS的方法 setName

   [webView evaluateJavaScript:@"setname('張三')" completionHandler:nil];

//此處 setname為JS定義的方法名, 內部 ‘張三’為傳給JS的引數。 如果setname方法需要傳入一個json或者array等非字元引數, 需要用format方法將其轉為string型別,在呼叫evaluate方法。例如

   NSString * para = [NSString stringWithFormat:@"setname('%@')",json];

首先我要強調的是,這樣的呼叫是沒有問題的 但是在實際應用中,由於我比較笨,H5和JS的相關程式碼不懂,所以,即便是這樣的方法呼叫方法也是看不懂的,因為實際開發過程中不會有簡單的setname(張三)這麼簡單,接下來我說明一下我遇到的坑。

我的應用場景: 點選某個按鈕判斷iOS端是否打開了推送。
首先點選按鈕 是OC呼叫JS,哪麼是否開啟了推送有一個YES和NO要傳給JS端,我就是在給JS傳引數的時候遇到的一些坑。

請看下面的程式碼。 其中parma 是我們要傳給JS的引數 ,cbDispatcher是OC與JS約定好的方法名,只有掉相同的方法名才能掉的通,

NSDictionary * parma = @{@"status":@"0"};
            if ([NSJSONSerialization isValidJSONObject:parma]) {
                NSError * error;
                NSData * jsonData = [NSJSONSerialization dataWithJSONObject:parma options:NSJSONWritingPrettyPrinted error:&error];
                NSString * jsonStr = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];
                NSString * backStr = [NSString stringWithFormat:@"%@(%@,%@)",dicPrama[@"cbDispatcher"],dicPrama[@"callbackId"],jsonStr];
                
                [web evaluateJavaScript:backStr completionHandler:^(id _Nullable object, NSError * _Nullable error) {
                    NSLog(@" - %@ -- %@ --- ",error,object);
                }];
            }

如果這樣寫的話,會有報錯,請看下圖

[web evaluateJavaScript:[NSString stringWithFormat:@"cbDispatcher('cbDispatcher(2,%@)')",jsonStr] completionHandler:nil];

請不要這樣寫,最好能把completionHandler這個引數的block寫成nil,因為可能,無法一遍就成功,這裡可以列印錯誤嗎,便於改成錯誤。
如下建議這樣寫:

[web evaluateJavaScript:backStr completionHandler:^(id _Nullable object, NSError * _Nullable error) {
                    NSLog(@" - %@ -- %@ --- ",error,object);
                }];

錯誤 Error Domain=WKErrorDomain Code=4 "A JavaScript exception occurred"
在這裡插入圖片描述

注意:遇到這個問題一定是 json解析dictionary出問題了,或者說拼接字串時最後傳的字串格式有問題,所以,這個錯誤的大致意思是 JS 不認識你傳過來的string。仔細看發現 在字串中不應該加 那 一對單引號導致這個stringH5就不認識了.
修改如下:
在這裡插入圖片描述
注意我圈出來的和之前的區別,經這樣修改就可以了
正確的截圖,如果completionHandler引數中返回兩個null那麼表示傳參就成功了。截圖如下在這裡插入圖片描述

拓展 查資料,發現有說這是nsdictionary 在執行json解析的時候設定json格式不爭取導致的。NSData * jsonData = [NSJSONSerialization dataWithJSONObject:parma options:NSJSONWritingPrettyPrinted error:&error]; option後的引數使用不正確,應該是NSData * jsonData = [NSJSONSerialization dataWithJSONObject:parma options:kNilOptions error:&error];這樣

從字面意思看,NSJSONWritingPrettyPrinted 是指json格式是:寫成漂亮的印刷,大概意思是:這樣的json也是有格式的,這個寫入選項會使用空格和縮排來使輸出更有可讀性。
如果這個選項沒有設定,則生成緊湊合理的JSON表示式。
如果使用 kNilOptions 表示,沒有什麼格式,就是一長溜的字串。
但是經過我的測試,這兩種json格式我們的JS時都認可的 。可能有朋友的JS不認第一種格式。請謹慎使用。

我是磊懷 QQ:2849765859 歡迎各位大佬聯絡我。