Vue与原生(ios)交互(相互传值)
金蝶云社区-honey缘木鱼
honey缘木鱼
78人赞赏了该文章 4,544次浏览 未经作者许可,禁止转载编辑于2018年12月17日 19:30:28
summary-icon摘要由AI智能服务提供

本文介绍了在原生iOS项目中集成Vue编写的商城项目,并实现了Vue与原生iOS之间的交互。具体分为UIWebView和WKWebView两种方式。UIWebView通过JavaScriptCore框架实现Vue调用OC方法,并解决了内存泄漏问题。WKWebView则通过WKScriptMessageHandler协议实现Vue与OC的交互。同时,文章还说明了Vue方法如何暴露给原生iOS调用,并给出了登录回调的示例代码。

用vue写的商城项目需要集成在原生的移动端项目中,并且登录,分享和支付都是调用原来项目的页面和方法,这就需要原生webView与Vue的交互,下面分别用UIWebView和WKWebView来实现与Vue的交互。



                                         一.UIWebView与Vue的交互

  Vue调用OC的方法

  1. iOS控制器.h文件引入<JavaScriptCore/JavaScriptCore.h>,并声明JSContext类的属性


   #import <JavaScriptCore/JavaScriptCore.h>

  @protocol JSObjcDelegate <JSExport>

  -(void)call:(NSString*)payStr payType:(NSString*)payType;//支付

  -(void)backPage;//返回原生t页面

  -(void)gotoLogin;//去登录

  -(void)gotoShare:(NSString*)prodectInfo;//分享

   @end

  @interface MallViewController : SMBaseViewController<UIWebViewDelegate,JSObjcDelegate>

  @property(strong,nonatomic)UIWebView*resultwebV;

  @property(nonatomic,strong)JSContext*JScontext;

 @end


2.在控制器.m文件中 UIWebViewDelegate的代理方法里面用context属性声明一个方法供js调用

- (void)viewDidLoad 

  {

    self.resultwebV = [[UIWebView alloc]initWithFrame:CGRectMake(0, -20, kScreenWidth, kScreenHeight+20)];

    self.resultwebV.delegate = self;

      self.resultwebV.scrollView.bounces = NO;

     NSString *textAccount  = USERMODEL.code;

     NSString*isLogin;

     if(USERMODEL.isLogin){

        isLogin = @"ture";

     }else{

         isLogin = @"false";

       }

        [self.resultwebV loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:[NSString               stringWithFormat:@"http://192.168.0.120:8081/#/?         userCode=%@&isLogin=%@&fm=%@",textAccount,isLogin,@"fromApp"]]]];

    [self.view addSubview:self.resultwebV];

 }


-(void)webViewDidFinishLoad:(UIWebView *)webView{

     [IHUtility removeWaitingView];

    _JScontext = [self.resultwebV valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"];

    self.JScontext[@"tianbai"] = self;

    self.JScontext.exceptionHandler = ^(JSContext *context, JSValue *ex){

        context.exception = ex;

        NSLog(@"异常信息%@",ex);

    };

}

documentView.webView.mainFrame.javaScriptContext 是为了获取JSContext的路径。

tianbai 是和web前端约定好的JS和oc桥接的桥梁对象,通过将这个桥梁对象注入iOS端的webView,JS前端就可以通过这个桥梁对象去调用原生应用的方法。

 self.JScontext[@"tianbai"] = self 这样JSContext环境引用控制器self,在退出控制器的时候,因为控制器self被JSContext引用而不释放,而JSContext只有等控制器释放了才能随之释放,所以就引起了循环引用,造成内存泄露。

解决泄漏方法:

-(void)viewDidDisappear:(BOOL)animated{

    [super viewDidDisappear:animated];

    if (self.JScontext) {

        self.JScontext[@"tianbai"] = nil;

    }

}

3. 在vue中methods:方法中调用原生支付方法

0136C322-531C-4075-AEC2-69A1ECE6785B.png

  • iOS调用Vue方法

  1.Vue的方法给原生调用,则需要把方法挂在window下面,在Vue的mounted方法中引入如图:

   

85C714A2-1B83-416B-89B2-1850D19B59F1.png

2. 在methods方法中具体实现登录后回调

// 登录返回
loginBack: function (data) {
  var _this = this
  localStorage.setItem('account', data)
  this.getLoginToken(data).then(function (token) {
    _this.getUserAdress()
  })
}

3.在iOS中写这些代码:

NSString *account = notification.object[@"account"]; 
JSValue *callBack = self.JScontext[@"loginBack"];
[callBack callWithArguments:@[account]];

   



二.WKWebView与Vue交互

Vue调用OC的方法


1.在控制器.h文件中

#import <WebKit/WebKit.h>
  @interface MallViewController : SMBaseViewController<WKUIDelegate,WKNavigationDelegate,WKScriptMessageHandler>@
property(nonatomic,strong) WKWebView * webView;
@property(nonatomic,weak) MBProgressHUD*hud;
@end


2.在控制器.m文件 

WKWebView*webV=[[WKWebView alloc] initWithFrame:[UIScreen mainScreen].bounds configuration:configuration];

[self.view addSubview:webV];

_resultwebV=webV;

webV.UIDelegate=self;

webV.navigationDelegate=self;

NSString *textAccount  = USERMODEL.code;

     NSString*isLogin;

     if(USERMODEL.isLogin){

        isLogin = @"ture";

     }else{

         isLogin = @"false";

       }

        [_resultwebV loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:[NSString               stringWithFormat:@"http://192.168.0.120:8081/#/?         userCode=%@&isLogin=%@&fm=%@",textAccount,isLogin,@"fromApp"]]]];


WKWebViewConfiguration *configuration = [[WKWebViewConfiguration alloc] init];

configuration.userContentController = [WKUserContentController new];

[configuration.userContentController addScriptMessageHandler:self name:@"tianbai"];



3.在WKScriptMessageHandler协议的代理方法里面根据message.name来判断js是否调用并作出相关的处理,message.body即为js传过来的参数


- (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message {

   NSLog(@"%@", message.body);

    NSLog(@"%@", message.name);

    NSDictionary * body = [message.body objectForKey:@"body"];

    if ([message.name isEqualToString:@"tianbai"]) {

        //执行

    }

}

4. 在vue中methods:方法中调用原生支付方法并传值

03102099-967E-4320-AD85-187EBFAFDB08.png

  • iOS调用Vue方法

    1. Vue的方法给原生调用,则需要把方法挂在window下面,在Vue的mounted方法中引入如图:



    85C714A2-1B83-416B-89B2-1850D19B59F1.png

    2. 在methods方法中具体实现登录后回调

     

// 登录返回
loginBack: function (data) {
  var _this = this
  localStorage.setItem('account', data)
  this.getLoginToken(data).then(function (token) {
    _this.getUserAdress()
  })
}

 3.在iOS中写这些代码:


   NSString *account = notification.object[@"account"];

    NSString *login = [NSString stringWithFormat:@"loginBack(%@)",account];

    [_resultwebV evaluatejsStr completionHandler:^(id _Nullable d, NSError * _Nullable error) {

        NSLog(@"%@",d);

        NSLog(@"%@",error);

    }];


Vue与原生的交互就这样实现了,如果又不懂的地方可以评论提出!



文章独发金蝶云社区

赞 78