OC与JS交互小结,JSON字符串传递规范

        这套协议在OC的Webview里面主要采用delegate的写法,一般与前端交互不使用第三方框架的情况下,JS给OC传值基本存在三种交互协议,但是每种协议都是需要和前端人员确认好方法名,两边要保持一致。 

 JS给OC传值,并调用OC方法 

        1.使用delegate的方式交互,此种方法在iOS7之后提出,通过JavaScriptCore这个框架进行交互,具体的代码在文后给出或者看代码。此种方法有一些需要注意的点,例如

-(NSString *)appVersion:(JSValue *)version{

         return"someThing";

 } 


在网上的一些文章中基本没有提到可以设置返回值,在这个方法里面可以直接return返回值,为同步回调。前端回传的参数类型为JSValue类型,如要解析,需要使用JSValue的toString方法,然后再转为NSDictionary即可。如果不定义接收参数其实使用delegate这种方式也是可以接收的,代码如下        

NSArray *arg = [JSContext currentArguments]; 

 JSValue *resouce = arg.firstObject; 

 此种情况适用于前端需要回传多个参数,但是写法又不能和安卓的冲突的时候。在delegate里面需要注意的还有这些代理方法都是出于子线程的,Xcode9增加了自动检测线程,注意线程问题。 

       2.使用Block进行交互,此种方法比较方便简洁, OC核心代码:

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

   JSContext *context = [webView   valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"]; 

 context[@"passValue"] = ^{ 

 NSArray *arg = [JSContext currentArguments]; 

 for (id obj in arg) { 

 NSLog(@"%@", obj); 

 } };

 } 

 JS核心代码是 

      function testClick() {

     var str1=document.getElementById("text1").value;

     var str2=document.getElementById("text2").value; 

      passValue(str1,str2); 

 } 

      注意:此代码需要放在webViewDidFinishLoad里面,这种方法应该是不可以设置前缀的

 3.使用拦截协议,两方定好协议头,如果传过来的协议头符合就做相应的处理,多用于页面按钮的一些跳转事件,比如点击客户咨询,跳转到原生的客户咨询界面。 

 JS代码:

 function testClick() { 

      var str1=document.getElementById("text1").value;

      var str2=document.getElementById("text2").value;

        // "objc://"为自定义协议头; // str1&str2为要传给OC的值,以":/"作为分隔                       window.location.href="objc://"+":/"+str1+":/"+str2; 

 } 

 在需要给OC传值的函数里(例如:testClick())写如上格式的代码 

 OC代码:

 //遵守UIWebViewDelegate代理协议。

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

 //拿到网页的实时url NSString *requestStr = [[request.URL absoluteString] stringByRemovingPercentEncoding]; /

/在url中寻找自定义协议头"objc://" 

 // 格式 objc://loadUrl/blog.csdn.net 协议/方法/网址 

 //判断链接中的协议头,如果是objc://, 则进行相关操作

 if ([requestStr hasPrefix:@"objc://"]) { 

 //拿到除去协议头的后部 NSString *urlContent = [urlStr substringFromIndex:[@"objc://" length]]; NSLog(@"%@", urlContent); //用/来拆分字符串 

 NSArray *urls = [urlContent componentsSeparatedByString:@"/"]; 

 NSLog(@"拆分的结果为:%@", urls); 

 //怕重复可以多定义一个头aaa,也可省略

 if ([@"aaa.toChat" isEqualToString:urls[0]]){ 

 [self pushChatView];

 }

 return NO; 

 } 

 return YES; 

 } 

 -(void)pushChatView{ 

 //具体业务代码

 } 

 OC调用JC方法并传值:

  [_webView stringByEvaluatingJavaScriptFromString:[NSString stringWithFormat:@"window.sendOCData&&window.sendOCData('%@')",parameter]];

 parameter是需要传递的值,建议为JSON字符串,注意%@外面是一个单引号,另外传递给JSON的字符串不要使用自动换行方法encode,先把NSDictionary转为NSData再转为NSString,代码如下 

 NSData *paramsJsonData = [NSJSONSerialization dataWithJSONObject:params options:0 error:nil]; //NSJSONWritingPrettyPrinted不要使用这些加了自动换行的,不然 前端无法接收 

 NSString * paramsStr = [[NSString alloc] initWithData:paramsJsonData encoding:NSUTF8StringEncoding]; 

 还有如果项目中即用了delegate又使用拦截协议,而且定义的协议头一样,那么会首先执行delegate的,拦截协议无法生效,所以如果需要使用两种,那么请定义不同的协议头。 

参考网址: 

http://blog.csdn.net/leaderqiu/article/details/51955956 http://www.cnblogs.com/yueyuanyueyuan/p/5651266.html 

 http://www.cocoachina.com/cms/wap.php?action=article&id=15105 http://blog.csdn.net/u012963325/article/details/51134574 

http://www.jianshu.com/p/063d748e072d

 delegate的主要代码 OC代码:

#import "ViewController.h"

#import JavaScriptCore/JavaScriptCore.h 尖括号

@protocol JSObjcDelegate

- (void)callCamera;

- (void)share:(NSString *)shareString;

@end

@interface ViewController () UIWebViewDelegate,JSExport 尖括号

@property (nonatomic, strong) JSContext *jsContext;

@property (strong, nonatomic) UIWebView *webView;

@end@implementation ViewController

#pragma mark - Life Circle

- (void)viewDidLoad {

 [super viewDidLoad]; 

 self.webView = [[UIWebView alloc]initWithFrame:self.view.bounds];

 [self.view addSubview:self.webView]; 

 self.webView.userInteractionEnabled = YES; 

 NSURL *url = [[NSBundle mainBundle] URLForResource:@"test" withExtension:@"html"]; self.webView.delegate = self; [self.webView loadRequest:[[NSURLRequest alloc] initWithURL:url]]; 

 }

#pragma mark - UIWebViewDelegate

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

 __weak typeof(self) weakSelf = self; self.jsContext = [webView valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"]; 

 self.jsContext[@"Toyun"] = self; 

 self.jsContext.exceptionHandler = ^(JSContext *context, JSValue *exceptionValue) { 

 context.exception = exceptionValue;

 NSLog(@"异常信息:%@", exceptionValue

);

 }; 

 }

#pragma mark - JSObjcDelegate

- (void)callCamera { 

 NSLog(@"callCamera"); // 获取到照片之后在回调js的方法picCallback把图片传出去 JSValue *picCallback = self.jsContext[@"picCallback"]; 

 [picCallback callWithArguments:@[@"photos"]];

}

- (void)share:(NSString *)shareString { 

 NSLog(@"share:%@", shareString); // 分享成功回调js的方法shareCallback JSValue *shareCallback = self.jsContext[@"shareCallback"]; 

 [shareCallback callWithArguments:nil];

}

@end

JS代码:

Objective-C和JavaScript交互的那些事

var callShare = function() {

var shareInfo = JSON.stringify({"title": "标题", "desc": "内容", "shareUrl": "http://www.jianshu.com/p/f896d73c670a",

"shareIco":"http://upload-images.jianshu.io/upload_images/1192353-fd26211d54aea8a9.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240"});

Toyun.share(shareInfo);

}

var picCallback = function(photos) {

alert(photos);

}

var shareCallback = function(){

alert('success');

}

能力有限有错误的话请指出,谢谢,排版是直接先在公司的worktile上先写再复制过来的,各位勉强看吧

你可能感兴趣的:(OC与JS交互小结,JSON字符串传递规范)