美文网首页
Objective-C与JavaScript交互初探

Objective-C与JavaScript交互初探

作者: 左左4143 | 来源:发表于2017-12-01 15:49 被阅读63次
    背景

    之前在工程中用到webView的情况大多都是一些协议条款之类简单的东西并没有交互的要求,所以只用一个UIWebView展示了出来,最近公司出了一个活动需要快速上线,主体是前端同事做的,但是一些功能还需要移动端支持,所以产生了交互的需求,目前是一个初步的方案。

    大致方案

    我采用的方案是封装了一个父类的ViewController, 将webView与一些基本的需要设置的东西(例如右上角菜单,访问网页时传入cookie)以及一些通用的交互方法(如分享,保存图片到本地)封装到着各类中,然后根据不同的业务创建不同的子类,子类可以根据自身需求加入独有的交互方法,方便管理。

    代码
    • 父类的实现

    1、采用WebViewJavascriptBridge实现交互,子类可以通过重写- (void)JavaScriptCallObjectiveC- (void)ObjectiveCCallJavaScript方法来实现自己独有的交互需求
    2、返回按钮在webView进入二级页面时会变成一个返回按钮(用来返回上一页)、一个关闭按钮(用来直接关闭Controller)
    3、注意这里我采用了一个进度条的第三方 NJKWebViewProgress 如果处理不当会与WebViewJavascriptBridge产生冲突,解决方法可以参照我的另一篇文章
    4、- (void)setCookiesForURL:(NSURL *)url方法是为webView设置Cookie (比如我们某些页面防止有人恶意访问,会验证用户的真实性,还有就是传入app版本让前端来做一些判断)

    #import <UIKit/UIKit.h>
    #import <WebViewJavascriptBridge.h>
    
    @interface ZCQGBaseWebViewViewController : UIViewController
    
    - (instancetype)initWithUrlString:(NSString *)urlString title:(NSString *)title;
    
    @property (nonatomic, strong) UIWebView *webView;
    @property (nonatomic, strong) WebViewJavascriptBridge *jsBridge;//bridge实体
    
    @property (nonatomic, assign) BOOL canShare;//能否分享
    @property (nonatomic, assign) BOOL needCookie;//是否需要传token和userId
    
    - (void)JavaScriptCallObjectiveC;//JS调用OC的方法
    - (void)ObjectiveCCallJavaScript;//OC调用JS的方法
    
    //.m中
    - (void)viewDidLoad {
        [super viewDidLoad];
        [self initNavigationView];//初始化navigationView
        [self cleanCookies];//清除cookie
        [self createWebView];//创建webView
    }
    
    - (void)initNavigationView {
        self.navigationItem.title = self.headTitle;
        self.view.backgroundColor = [UIColor whiteColor];
        self.navigationController.navigationBar.tintColor = [UIColor whiteColor];
        self.navigationController.navigationBar.titleTextAttributes = @{NSForegroundColorAttributeName: [UIColor whiteColor], NSFontAttributeName : [UIFont navTitleFont]};
        self.navigationItem.leftBarButtonItem = [[UIBarButtonItem alloc] initWithImage:[UIImage imageNamed:@"arrow_back"] style:UIBarButtonItemStylePlain target:self action:@selector(customBackItemAction:)];
        self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithImage:[UIImage imageNamed:@"TD_icon_more"] style:UIBarButtonItemStylePlain target:self action:@selector(moreAction:)];
    }
    
    - (void)cleanCookies {
        NSHTTPCookieStorage *storage = [NSHTTPCookieStorage sharedHTTPCookieStorage];
        for (NSHTTPCookie *cookie in [storage cookies]) {
            [storage deleteCookie:cookie];
        }
        [[NSURLCache sharedURLCache] removeAllCachedResponses];
    }
    
    - (void)createWebView {
        
        self.webView = [[UIWebView alloc] initWithFrame:self.view.bounds];
        self.webView.opaque = NO;
        self.webView.backgroundColor = [UIColor clearColor];
        self.webView.scrollView.bounces = NO;
        self.webView.scrollView.showsVerticalScrollIndicator = NO;
        [self.view addSubview:self.webView];
        [WebViewJavascriptBridge enableLogging];
        self.jsBridge = [WebViewJavascriptBridge bridgeForWebView:self.webView];
        [self.jsBridge setWebViewDelegate:self];
        [self baseJavaScriptCallObjectiveC];
        
        [self JavaScriptCallObjectiveC];
        
        webViewProgress = [[NJKWebViewProgress alloc] init];
        self.webView.delegate = webViewProgress;
        webViewProgress.webViewProxyDelegate = self.jsBridge;
        webViewProgress.progressDelegate = self;
        
        webViewProgressView = [[NJKWebViewProgressView alloc] init];
        webViewProgressView.frame = CGRectMake(0, 64, SCREEN_WIDTH, 3);
        webViewProgressView.progressBarView.backgroundColor = RGBAVALUECOLOR(0x40F44A, 0.8);
        webViewProgressView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleTopMargin;
        [webViewProgressView setProgress:0 animated:YES];
        [self.view addSubview:webViewProgressView];
        
        NSString *newUrl = [self.urlString stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
        newUrl = [newUrl stringByReplacingOccurrencesOfString:@" " withString:@""];
        NSURLRequest *request =[NSURLRequest requestWithURL:[NSURL URLWithString:newUrl]];
        [self.webView loadRequest:request];
    }
    //基类实现的JS调OC方法
    - (void)baseJavaScriptCallObjectiveC {
    
        __weak ZCQGBaseWebViewViewController *weakSelf = self;
        //默认的native分享方法
        [self.jsBridge registerHandler:defaultShareMethod handler:^(id data, WVJBResponseCallback responseCallback) {
            if (![[ZCQShareManager manager] detectPlatforms]) {
                [weakSelf showHint:@" 未检测到可以分享的平台 "];
                return;
            }
            NSDictionary *result = (NSDictionary *)data;
            ZCQShareUrlModel *model = [[ZCQShareUrlModel alloc] init];
            model.shareTitle = (NSString *)result[@"title"];
            model.shareUrl = (NSString *)result[@"shareUrl"];
            model.descriptionString = (NSString *)result[@"description"];
            model.shareImage = (NSString *)result[@"shareImgPath"];
            [[ZCQShareManager manager] openShareViewWithModel:model completion:^(ZCQShareType type) {
                NSLog(@"%ld",type);
            }result:^(NSError *error, ZCQShareType type) {
                
            }];
        }];
    }
    - (void)JavaScriptCallObjectiveC {
        //交给子类重写实现
       
    }
    
    - (void)ObjectiveCCallJavaScript {
        //交给子类重写实现
        
    }
    
    - (void)setCookiesForURL:(NSURL *)url {
        if (!self.needCookie) {
            return;
        }
        //设置token 和 userId
        NSString *host = [url host];
        NSString *path = [url path];
        if (host == nil || path == nil) {
            return;
        }
        
        NSString *appToken = [ZCQUserManager manager].token;
        if(appToken){
            NSHTTPCookie *tokenCookie = [NSHTTPCookie cookieWithProperties:@{NSHTTPCookieDomain:[url host],NSHTTPCookiePath:[url path],NSHTTPCookieName:@"x-auth-token",NSHTTPCookieValue:[ZCQUserManager manager].token}];
            [[NSHTTPCookieStorage sharedHTTPCookieStorage] setCookie:tokenCookie];
        }
        
        NSString *userId = [ZCQUserManager manager].userModel.userId;
        if(userId){
            NSHTTPCookie *uidCookie = [NSHTTPCookie cookieWithProperties:@{NSHTTPCookieDomain:[url host],NSHTTPCookiePath:[url path],NSHTTPCookieName:@"uid",NSHTTPCookieValue:[ZCQUserManager manager].userModel.userId}];
            
            [[NSHTTPCookieStorage sharedHTTPCookieStorage] setCookie:uidCookie];
        }
        
        NSString *appVersion = [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleShortVersionString"];
        if (appVersion) {
            NSHTTPCookie *versionCookie = [NSHTTPCookie cookieWithProperties:@{NSHTTPCookieDomain:[url host],NSHTTPCookiePath:[url path],NSHTTPCookieName:@"zcqAppVersion",NSHTTPCookieValue:appVersion}];
            [[NSHTTPCookieStorage sharedHTTPCookieStorage] setCookie:versionCookie];
        }
        
    }
    
    
    • 子类的实现

    此时 就可以根据不同的业务类型来写一些子类来实现不同的功能,只需要根据要求将- (void)JavaScriptCallObjectiveC- (void)ObjectiveCCallJavaScript方法重写就可以了。

    由于涉及到某些具体的业务,并没有将所有代码贴出来,有什么疑问可以联系我qq:329592157,有什么建议也可以和我分享,祝大家早日升职加薪,步入人生巅峰!

    相关文章

      网友评论

          本文标题:Objective-C与JavaScript交互初探

          本文链接:https://www.haomeiwen.com/subject/nudwbxtx.html