iOS微信分享&h5和原生app交互

其实微信分享和微信支付要配置的东西差不多,而且在一个应用里面是用一个Appkey的不需要重新申请。而且代码中有很多重复的地方。

(一)分享

准备工作:注册微信Appkey

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    [WXApi registerApp:@"wxd930ea5d5a258f4f" withDescription:@"测试demo"];
    return YES;
}

2.构建微信分享的信息,调起微信SDK,跳转到微信
// [WXApi sendReq:req]; 打开微信

//分享文字给好友 
       SendMessageToWXReq *req = [[SendMessageToWXReq alloc] init];
        req.text = @"测试把信息分享到微信好友";
        req.bText = YES;
        req.scene = WXSceneSession;//会话(WXSceneSession)或者朋友圈(WXSceneTimeline)

        [WXApi sendReq:req];

//分享图片给好友
        WXMediaMessage *message = [WXMediaMessage message];
        message.title = @"测试把图片分享到微信好友";
        [message setThumbImage:[UIImage imageNamed:@"IconWX.png"]];
        WXImageObject *imageObject = [[WXImageObject alloc] init];
        NSString *filePath = [[NSBundle mainBundle] pathForResource:@"IconWX" ofType:@"png"];
        imageObject.imageData = [NSData dataWithContentsOfFile:filePath];
        message.mediaObject = imageObject;
        SendMessageToWXReq *req = [[SendMessageToWXReq alloc] init];
        req.bText = NO;
        req.message = message;
        req.scene = WXSceneSession;        
        [WXApi sendReq:req];

   //分享网页给好友
        WXMediaMessage *message = [WXMediaMessage message];
        message.title = @"测试把web分享到微信好友";
        [message setThumbImage:[UIImage imageNamed:@"IconWX.png"]];

        WXWebpageObject *webObject = [WXWebpageObject object];
        webObject.webpageUrl = @"http://www.baidu.com";
        message.mediaObject = webObject;

        SendMessageToWXReq *req = [[SendMessageToWXReq alloc] init];
        req.bText = NO;
        req.message = message;
        req.scene = WXSceneSession;

        [WXApi sendReq:req];

 //分享文字到朋友圈
        SendMessageToWXReq *req = [[SendMessageToWXReq alloc] init];
        req.text = @"测试把信息分享到微信朋友圈";
        req.bText = YES;
        req.scene = WXSceneTimeline;//会话(WXSceneSession)或者朋友圈(WXSceneTimeline)
        [WXApi sendReq:req];

 //分享图片到朋友圈 
        WXMediaMessage *message = [WXMediaMessage message];
        message.title = @"测试把图片分享到微信朋友圈";
        [message setThumbImage:[UIImage imageNamed:@"IconWX.png"]];
        WXImageObject *imageObject = [[WXImageObject alloc] init];
        NSString *filePath = [[NSBundle mainBundle] pathForResource:@"IconWX" ofType:@"png"];
        imageObject.imageData = [NSData dataWithContentsOfFile:filePath];
        message.mediaObject = imageObject;

        SendMessageToWXReq *req = [[SendMessageToWXReq alloc] init];
        req.bText = NO;
        req.message = message;
        req.scene = WXSceneTimeline;

        [WXApi sendReq:req];

//分享网页到朋友圈
        WXMediaMessage *message = [WXMediaMessage message];
        message.title = @"测试把web分享到微信朋友圈";
        message.description = @"";
        [message setThumbImage:[UIImage imageNamed:@"IconWX.png"]];

        WXWebpageObject *webObject = [WXWebpageObject object];
        webObject.webpageUrl = @"http://www.baidu.com";
        message.mediaObject = webObject;

        SendMessageToWXReq *req = [[SendMessageToWXReq alloc] init];
        req.bText = NO;
        req.message = message;
        req.scene = WXSceneTimeline;

        [WXApi sendReq:req];

2.微信回调代理设置,打开你的app

//9.0前的方法,为了适配低版本 保留
- (BOOL)application:(UIApplication *)application handleOpenURL:(NSURL *)url{
    return [WXApi handleOpenURL:url delegate:self];
}

- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation{

    return [WXApi handleOpenURL:url delegate:self];
}

//9.0后的方法
- (BOOL)application:(UIApplication *)app openURL:(NSURL *)url options:(NSDictionary *)options{
     //这里判断是否发起的请求为微信支付,如果是的话,用WXApi的方法调起微信客户端的支付页面(://pay 之前的那串字符串就是你的APPID,)
     //处理微信通过URL启动App时传递的数据,delegate代表在哪个类接收返回的请求,有时为了简化AppDelegate可以delegate设置为一个单利类,在单独的一个类处理微信回调的数据

     //这个方法调起之后在点击返回商户之后会打开你的app,(对应第9步)
        return  [WXApi handleOpenURL:url delegate:self];
}

4.微信回调信息接收的地方

//微信SDK自带的方法,处理从微信客户端完成操作后返回程序之后的回调方法,显示分享结果
-(void) onResp:(BaseResp*)resp
{
    if([resp isKindOfClass:[SendMessageToWXResp class]])
    {
        NSString *result = (resp.errCode == WXSuccess) ?KShareResultIsYes :KShareResultIsNo;
        [[NSNotificationCenter defaultCenter] postNotificationName:KShareResultNotification object:result];
    }
}

注:其实微信分享和微信支付在配置上很类似,微信分享的难点并不在这里,而是在于和h5界面的相互上。

(二)分享进阶:h5和原生app的交互

1.模拟情景:

1)app有一个模块是我的优惠券,这个优惠券的信息是UIWebView控件加载的h5界面,这些优惠券可以分享(转增)给我的朋友;
2)点击转增按钮,会打开微信客户端,将一条优惠券信息分享给我的朋友,
3)朋友在微信客户端点击之后,在微信的浏览器打开,然后可以领卷。
4)然后我在我的客户端可以查询到我的优惠券已经被朋友领取了,我的优惠券状态变为不可使用。

tips:需要注意的是分享分两种
1.分享给别人与自己无关
2.转增(分享)给别人,自己没有了

在第2种情况下分享信息给朋友并不是很难的部分,难点是如何和h5界面还有后端交互信息才是我们需要注意的地方。

2.转增优惠券流程展示
iOS微信分享&h5和原生app交互_第1张图片
屏幕快照 2017-11-16 13.34.14.png
3.实现原理

1.app截取webview的请求,经过判断发现是分享请求,就封装这条分享信息,调起微信Sdk,打开微信客户端进将这条信息分享给微信。
2.朋友接收到分享信息之后,在微信内置的浏览器中打开这个分享界面(h5),点击领取。
3.优惠券平台接收到优惠券已经被领取的信息后,修改优惠券状态。
4.当回到app时,重新加载h5界面。h5界面是由优惠券平台提供的数据,且在第三步优惠券的状态已经被改变了。

注:优惠券有3个状态: 1.可转增(可使用) 2.转增中(不可使用)3.已转增(不可使用)

4.ios代码实现

1.设置webview 加载网页
2.实现协议方法
3.实现网络截取后相应的方法

-(BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType
{
    //获取自己的网络请求的网址字符串
     NSString *urlString = [request.URL absoluteString];
    //这个url字符串可能是 


    //自己定义的协议前缀  网页部分一会儿也是要设置成这个协议!
    NSString *scheme = @"xmg://mailshare";
    //打印出自己获取的网络请求的网址是什么
    NSLog(@"~~~~~ %@",url);
    //解析网址前缀是否为@"xmg://mailshare"
    if ([url hasPrefix:scheme])
    {
       //在这里对截取到的信息进行处理,封装后,调起微信分享的SDK,进行分享,也就是第一部分的第二步
         、、、、、、、、、、、、、、、、、、、、
        //不加载这个网络请求的页面,返回NO,代表了这个对应的点击事件不由h5页面处理,而是交给了原生的app进行处理,
        return NO;
    }
    //YES:加载这个网络请求的页面
    return YES;
}
5.h5代码实现
iOS微信分享&h5和原生app交互_第2张图片
屏幕快照 2017-11-16 14.03.18.png
  • 只需要在连接的地方,将href的改成自己设定的协议+方法名即可!
代码解释:

1.可交互前提:
iOS和h5界面的开发人员一起约定了xmg://mailshare代表了对应的按钮的点击事件是分享事件, 一般情况下来说NSString *urlString = [request.URL absoluteString];,这个urlString应该是“xml://mailshare+一个字典”,这个字典里面有这个按钮的相关信息,在ios端处理的时候一般是截取到最后一个字段,然后将这个字段的信息取出,在封装为分享的数据类型,然后传给微信。整个urlString都需要ios的开发人员和h5界面的开发人员约定好的。

(三)h5和原生app的交互

背景:

上面的交互只是单方面在OC处的webview协议方法解决,解析截取到的网络请求,这种方法实现起来比较快捷,但是JS得不到回执啦,

解决办法:

利用WebViewJavascriptBridge第三方库进行JS和OC的桥接

好处

利用桥接的话,就可以进行双方的通信,JS部分可以做回执处理,OC部分也可以做回执处理。 注意点就是JS的Handle要命名好,OC部分的Handle也要命名好,不要搞混淆。

1.ios端代码:
#import "ViewController.h"
#import "WebViewJavascriptBridge.h"
@interface ViewController ()

//声明`WebViewJavascriptBridge`对象为属性
@property (nonatomic,strong)  WebViewJavascriptBridge * bridge;

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
}

-(void)viewWillAppear:(BOOL)animated{
    if (_bridge) { return; }

    //用UIWebView加载web网页
    UIWebView * webview = [[UIWebView alloc]initWithFrame:self.view.bounds];
    webview.delegate = self;
    [self.view addSubview:webview];

    //设置能够进行桥接
    [WebViewJavascriptBridge enableLogging];

    _bridge = [WebViewJavascriptBridge bridgeForWebView:webview];

    [_bridge registerHandler:@"facebookObjcCallback" handler:^(id data, WVJBResponseCallback responseCallback) {
        NSLog(@" ======FacebookObjcCallback =========  %@", data);

        //传话给网页说已经接收到
        responseCallback(@"facebookObjcCallback回复网页,已经收到消息");

        //

    }];

    [_bridge registerHandler:@"QQShareObjcCallback" handler:^(id data, WVJBResponseCallback responseCallback) {
        NSLog(@" ======QQShareObjcCallback ========= %@", data);

        //传话给网页说已经接收到
        responseCallback(@"QQShareObjcCallback回复网页,已经收到消息");


    }];

    [_bridge registerHandler:@"WXShareObjcCallback" handler:^(id data, WVJBResponseCallback responseCallback) {
        NSLog(@" ======WXShareObjcCallback =========  %@", data);

        //传话给网页说已经接收到
        responseCallback(@"WXShareObjcCallback回复网页,已经收到消息");

        //

    }];

    [_bridge registerHandler:@"MessageShareObjcCallback" handler:^(id data, WVJBResponseCallback responseCallback) {
        NSLog(@" ======MessageShareObjcCallback =========  %@", data);

        //传话给网页说已经接收到
        responseCallback(@"MessageShareObjcCallback回复网页,已经收到消息");

        //

    }];

    [_bridge registerHandler:@"MailShareObjcCallback" handler:^(id data, WVJBResponseCallback responseCallback) {
        NSLog(@" ======MailShareObjcCallback =========  %@", data);

        //传话给网页说已经接收到
        responseCallback(@"MailShareObjcCallback回复网页,已经收到消息");

        //

    }];

    // oc传话给JS(网页执行)  网页部分会执行以下代码:
    /*
     bridge.registerHandler('testJavascriptHandler', function(data, responseCallback) {
     log('ObjC called testJavascriptHandler with', data)
     var responseData = { 'Javascript Says':'Right back atcha!' }
     log('JS responding with', responseData)
     responseCallback(responseData)
     })
     接收
     */

    //网页接收OC的方法句柄名叫testJavascriptHandler  此时OC给JS传的数据是@{ @"foo":@"before ready" }
    [_bridge callHandler:@"testJavascriptHandler" data:@{ @"foo":@"before ready" }];

   // 自定义按钮 此处没用,需要的可以自己打开使用
   // [self renderButtons:webView];
    //当你没有把网页放入服务器的话,可以把网页放在本地工程,这个时候就要执行以下的方法,用NSBoundle加载本地文件
   // [self loadExamplePage:webview];

}

 //自定义按钮
 - (void)renderButtons:(UIWebView*)webView {
    UIFont* font = [UIFont fontWithName:@"HelveticaNeue" size:12.0];

    UIButton *callbackButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
    [callbackButton setTitle:@"呼叫JS的Handle" forState:UIControlStateNormal];
    [callbackButton addTarget:self action:@selector(callHandler:) forControlEvents:UIControlEventTouchUpInside];
    [self.view insertSubview:callbackButton aboveSubview:webView];
    callbackButton.frame = CGRectMake(10, 400, 100, 35);
    callbackButton.titleLabel.font = font;
}

 //可以通过自定义按钮实现方法,动态和JS进行交互
 //注:本代码中没有写按钮去实现此方法,需要的同学可以自己去定义按钮实现此方法
 - (void)callHandler:(id)sender {

    id data = @{ @"OC第一次发信息给JS": @"Hi there, JS,I am OC !" };
    // testJavascriptHandler是JS部分接收OC传送消息的方法句柄
    // data 是OC给JS传的数据
    // response是JS接收到消息后给OC传的数据
    [_bridge callHandler:@"testJavascriptHandler" data:data responseCallback:^(id response) {
        NSLog(@"JS收到消息后,回复给OC的消息为: %@", response);
    }];

}

//加载本地网页
//本代码中的网页是从服务器获取,不是放在本地,放在本地的同学,可以用以下的方法加载
- (void)loadExamplePage:(UIWebView*)webView {
    NSString* htmlPath = [[NSBundle mainBundle] pathForResource:@"codetest" ofType:@"html"];
    NSString* appHtml = [NSString stringWithContentsOfFile:htmlPath encoding:NSUTF8StringEncoding error:nil];
    NSURL *baseURL = [NSURL fileURLWithPath:htmlPath];
    [webView loadHTMLString:appHtml baseURL:baseURL];
}
2.网页部分(JS部分)

①在script标签内写桥接方法
②在a标签内记得表面id唯一标示,以便script能够获取此标签元素



 


学习博客:
http://blog.csdn.net/boring_cat/article/details/51240819

你可能感兴趣的:(iOS微信分享&h5和原生app交互)