MHGJavascriptBridge簡介

用途

在iOS開發中,咱們常常會碰到這樣的需求:在UIWebView中的一個連接,點了以後不是進下一個網頁,而是進下一個UIViewController,或者讓ObjC代碼作點事情。這在資訊類的應用中很常見,好比網易新聞、騰訊新聞,以及咱們公司的東方財富通中的資訊。git

而在舊的iOS版本中,系統不提供在Javascript直接調用ObjC的方法。只能經過變換location等發起網絡請求的方式,使得UIWebViewDelegate中的- (BOOL)webView:shouldStartLoadWithRequest:navigationType:感知到,進而作ObjC的處理。github

然而這樣作比較不優雅,全部的事情都圍繞在URL請求上面,而不是方法調用上面,看上去不優雅。MHGJavascriptBridge的用意即是將URL請求等等封裝起來,讓Javascript和ObjC代碼注重於方法調用自己上來。web

Github地址:https://github.com/hikui/MHGJavascriptBridge數組

使用方法

MHGJavascriptBridge由3個文件組成,MHGJavascriptBridge.h, MHGJavascriptBridge.m, MHGJavascriptBridge.js。將這三個文件加入Xcode工程中。注意,MHGJavascriptBridge.js必須加入到資源文件中(在"Building phases" -> "Copy bundle resources"中出現),Xcode默認會將.js文件加入到Compile Sources裏面去,這是錯誤的。網絡

Objective C設置

首先,咱們須要初始化一個bridge,這一般是在一個UIViewController中進行的。這裏假設在UIViewController中對bridge進行初始化。在初始化中,須要設定bridge的webView屬性:異步

@interface MHGWebViewController ()<UIWebViewDelegate>

@property (nonatomic, strong) MHGJavascriptBridge *bridge;
@property (nonatomic, strong) UIWebView *webView;

@end

...

- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
    self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
    if (self) {
        _bridge = [[MHGJavascriptBridge alloc]init];
        _bridge.webView = self.webView;
    }
    return self;
}

在MHGJavascriptBridge中,全部能被Javascript調用的Objective C方法將以block的形式呈現。首先咱們須要定義一些blocks,而後對每個block起名。函數

- (void)viewDidLoad
{
    [super viewDidLoad];

    [self.bridge setBlockName:@"button1OnClick" block:^(NSDictionary *dict) {
        // do stuff
        NSLog(@"button1 on click with params:%@", dict);
    }];
    [self.bridge setBlockName:@"beginSomeTasks" block:^(NSDictionary *dict) {
        // do stuff
        NSLog(@"begin some tasks with params:%@", dict);
    }];
    ...
}

MHGJavascriptBridge的原理是構造特定的URL,而且用UIWebViewDelegate中的- (BOOL)webView:shouldStartLoadWithRequest:navigationType:攔截這個URL。因此在這個delegate方法中,咱們須要加入攔截語句:ui

- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType
{
    BOOL intercepted = [self.bridge interceptRequest:request]; //必須有
    // Do other things ...
    return YES;
}

其中,interceptRequest:方法會返回一個BOOL,若是攔截成功,則返回YESatom

這樣,Objective C部分就設置完成了。其中須要注意的是,block被調用時,會傳入一個dict,這是Javascript部分代碼調Objective C代碼時所傳的參數。url

Javascript設置

Javascript部分設置比較簡單,最基本的設置是要保證UIWebView中的HTML引入了MHGJavascriptBridge.js

<script src="MHGJavascriptBridge.js"></script>

Javascript調用Objective C代碼

一旦設置完成以後,Javascript和Objective C就能互相調用了。代碼以下:

var button1ClickEventHandler = function (){
    // Do stuff ...
    MHGJavascriptBridge.callNativeBlock('button1OnClick',{'url':imageURL});
};

<button onClick="button1ClickEventHandler()">button 1</button>

這時,點擊button1時,就能觸發Objective C的代碼了。MHGJavascriptBridge.callNativeBlock有兩個參數,第一個參數是在Objective C中註冊的block名字,第二個參數是傳給block裏面的dict的額外信息。其中第二個參數必須是一個字典(或者說是一個Javascript Object),或者什麼都不傳。

Objective C調用Javascript代碼

方法和上述相似:

...

[self.bridge callJavascriptFunction:@"setImageWithURL" withParams:@[fileURL.absoluteString]];

...

其中第一個參數是Javascript函數名。若是你在HTML中定義了function xxx(){}或者var xxx = function(){}的話,就能被調用。第二個參數是一個數組,傳的是Javascript函數要用的參數列。

侷限性

  • Javascript調用Objective C時,全部的調用都是異步的,暫時沒法實現同步調用。
  • Javascript調用Objective C時,所傳參數受URL長度限制而限制。
相關文章
相關標籤/搜索