iOS js交互遇到的问题

2018-12-17  本文已影响0人  温柔vs先生

iOS 关于js交互的代码已经很多了,我这里说一下我在开发中遇到的问题:

首先说一下最近开发过程中APP掉js代码时遇到的坑,看下面代码:

if (model) {
            // 初始化页面数据
            dispatch_async(dispatch_get_main_queue(), ^{
                JSValue *temfunction = _jsContext[@"appCallJsInitData"];
//                [temfunction.context[@"setTimeout"] callWithArguments:@[model]];
                [temfunction callWithArguments:@[model]];
            });
        }
其中非常重要的两句代码
1、 [temfunction callWithArguments:@[model]];

2、 [temfunction.context[@"setTimeout"] callWithArguments:@[model]];

第一种写法会在某些特定的时刻造成闪退的现象,网上推荐用第二种写法,但是在iOS12后这种写法会导致h5的界面加载不出来,至今没有找到原因,若以后知道会补充进来

第二种交互方法
if (model) {
            // 初始化页面数据
            NSString *jsonStr = [GeneralUtils transformDictionaryToJsonStr:model];
            jsonStr = [GeneralUtils transformSingleSlashToDoubleSlashWithJsonStr:jsonStr];
           
            dispatch_async(dispatch_get_main_queue(), ^{
                
                [_myWebView stringByEvaluatingJavaScriptFromString:[NSString stringWithFormat:@"appCallJsInitData('%@')",jsonStr]];
            });
  } 

他是通过webview自带的方法stringByEvaluatingJavaScriptFromString来把接口请求到的数据经过处理后的json串进行数据传递,目前项目中采用的是这种写法。但是官方有这样的提示:


image.png

译文: stringByEvaluatingJavaScriptFromString:方法同步等待JavaScript评估完成。如果您加载了尚未经过审核的JavaScript代码的Web内容,则调用此方法可能会导致您的应用挂起。最佳实践是采用WKWebView类并使用其evaluateJavaScript:completionHandler:方法。

第三种交互方法
if (model) {
            // 初始化页面数据
            NSString *jsonStr = [GeneralUtils transformDictionaryToJsonStr:model];
            jsonStr = [GeneralUtils transformSingleSlashToDoubleSlashWithJsonStr:jsonStr];
            dispatch_async(dispatch_get_main_queue(), ^{

                [_jsContext evaluateScript:[NSString stringWithFormat:@"appCallJsInitData('%@')",jsonStr]];
            });
        }

这种方法没有造成闪退的情况,但是在你连续进行交互时,界面有时并没有加载出来,出现白屏的现象。

以上是我在js交互中遇到的一些问题,在此记录下来,有待以后补充完善。

补充:

2018.12.18:
在第一种交互方法中,我说 (在iOS12后这种写法会导致h5的界面加载不出来)是不对的,首先我们要知道为什么要加setTimeout,设置setTimeout意味着加了一个延迟的方法,(在js的代码中对象获取值是异步进行的,类似iOS的异步,此时会造成不能保证拿到传递的数据后,对象被创建出来,所以要加一个延迟方法,保证对象都创建完毕,数据能够接受成功。)

h5代码:
/**
 * [appCalljsTellBinner app 传输轮播图片信息给js,并实例化]
 * @param  {[type]} arg [description]
 * @return {[type]}     [description]
 */
function appCalljsTellBinner(arg){
        if(arg.code == "0000" && arg.data && arg.data.list ){
            var data = arg.data;
//这里的vm可能没有及时创建出来,导致不能接收数据
            vm.carouselList = arg.data.list;
            Vue.nextTick(function () {
                //顶部,广告位轮播
                var carousel = new Swiper('#carousel .swiper-container',{
                    /*loop: true,*/
                    autoplay: 3000,
                    autoplayDisableOnInteraction:false,
                    lazyLoading : true,
                    lazyLoadingInPrevNext : true,
                    pagination : '.swiper-pagination',
                    preventLinksPropagation : true,
                    onInit:function(swiper){
                        setTimeout(function(){
                            document.querySelector('.swiper-pagination').style.opacity = 1;
                        },1000)
                    }
                });
            });
        }
}

但是在上面代码中

[temfunction.context[@"setTimeout"] callWithArguments:@[model]];

我们并没有设置延迟的时间所以需要加上这样的数据

[temfunction.context[@"setTimeout"] callWithArguments:@[temfunction, @0, model]];

callWithArguments后面跟的是一个数组,里面要另外加上我们的缓存时间和对象。至于数组里面能放多少元素,元素的位置有没有要求等,还不是很清楚,留待以后解决。

下面是官方对这个方法的介绍:

/*!
@methodgroup Calling Functions and Constructors
*/
/*!
@method
@abstract Invoke a JSValue as a function.
@discussion In JavaScript, if a function doesn't explicitly return a value then it
 implicitly returns the JavaScript value <code>undefined</code>.
@param arguments The arguments to pass to the function.
@result The return value of the function call. 
*/
- (JSValue *)callWithArguments:(NSArray *)arguments;

arguments传递给函数的参数。

上一篇下一篇

猜你喜欢

热点阅读