1. 程式人生 > >iOS webView的高階用法之JS互動

iOS webView的高階用法之JS互動

前言:說起JS互動,很多童鞋會黯然色變,感覺很高深的樣子。大部分小夥伴只知道一種,哪一種我也說說吧。

   1.在webView中將要請求的時候,攔截URL,進行重定向,然而該場景實用有限,網上資料也很多下面說說另一種互動方式。

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

  2.先說一下這種互動方式應用的場景吧。

     2.1:需求:假如貴公司在做一個金融專案,有一個版本功能需要提交個人資料資訊,只是為了一個業務需要,那麼通過h5做一套,然後iOS和Android只需要webView載入就行,明顯提高了開發效率。。。如果貴公司的其他產品也想接入這個功能,那也能通過webview方式直接用了,所謂是牛逼哄哄,通用性特別強。

         但是:(1):比如,webview裡有一個上傳身份證照片的功能,點選網頁,需要iOS端調起相簿功能。。如何互動??

                    (2): 載入的網頁中,點選一個按鈕,要檢視訂單詳情功能,但是需要傳會訂單號,怎麼辦:

                    (3): 點選下一步,,iOS端進入下一個介面;??

  這就牽扯到JS呼叫OC方法,傳遞引數等等。

 

3.本文將非常詳細的說明使用方法,一句程式碼不少的說明,你只需要按照步驟操作,一定能執行出你想要的JS互動場景,包你能派上大用場。。廢話不說了,開始吧

 

正文:JS互動,就是js 中通過一個物件來呼叫方法的

   1.js互動,首先我們要準備一個html檔案,沒有網頁檔案,要不然怎麼互動:至於這些東西怎麼建立,這裡不做介紹,樓主最後會附上聯絡方式,提供demo,demo中有,直接複製就行。

   1.1.首先準備一個html檔案,html檔案裡引用了外部的JS檔案

 

2.js檔案,裡面實現了html檔案裡的一些按鈕的點選事件

 

圖片裡非常清楚的註釋了一些重要程式碼的註釋,非常詳細,搞得自己很會h5一樣,程式設計師,不能放棄任何一次裝b的機會,

 

⚠️注意: 這裡在網頁中寫了4個按鈕,,分別調OC的方法

                   1. 點選按鈕,喚起系統相簿功能;

                   2. 就是簡單的調一個方法

                   3. 呼叫一個引數的方法

                   4. 呼叫多個引數的方法,這裡舉例是兩個。

 

  2.首先建立一個類 繼承NSObject ,並且規定一個協議,直接上程式碼

 2.1>建立TestJSObject.h標頭檔案

#import <Foundation/Foundation.h>

#import <JavaScriptCore/JavaScriptCore.h>

 

@protocol TestJSObjectProtocol <JSExport>

/// 調支付

- (void)ZTHpay;

/// 調系統相簿

- (void)ZTHShowPicker;

/// 傳引數回來 比如是一個訂單號

- (void)ZTHPassParameter:(NSString *)orderNumber;

/// 傳兩個引數回來 比如是訂單號,姓名

- (void)ZTHTestParameteroneAnd:(NSString *)orderNumber Parametertwo:(NSString *)name;

@end

 

 

@interface TestJSObject : NSObject<TestJSObjectProtocol>

///定義三種block,回撥到控制器中;

@property (nonatomic,copy)void(^showPickerBlock)();

 

@end

 

2.2:然後在.m中實現宣告的方法,這4個方法,都會被呼叫

#import "TestJSObject.h"

@implementation TestJSObject

- (void)ZTHpay{

    NSLog(@"調了支付了-----------------");

}

- (void)ZTHShowPicker{

    NSLog(@"調了相機-------------------");

    dispatch_async(dispatch_get_main_queue(), ^{

       //當然回撥後要處理的邏輯,肯定不能在這個類裡處理,這裡採用block回撥到控制器中處理,其餘的三種方式都可以用這種方式處理,這裡就不一一列舉了

        self.showPickerBlock();

    });

}

- (void)ZTHPassParameter:(NSString *)orderNumber{

    NSLog(@"%@", orderNumber);

}

//- (void)ZTHTestParameterone:(NSString *)orderNumber AndParametertwo:(NSString *)name{

//    NSLog(@"訂單號--%@姓名---%@", orderNumber, name);

//}

- (void)ZTHTestParameteroneAnd:(NSString *)orderNumber Parametertwo:(NSString *)name{

    NSLog(@"訂單號--%@姓名---%@", orderNumber, name);

}

@end

 

  3最後在控制器中

   3.1>在懶載入中,設定了web view的url,是一個本地檔案,也就是我們一開始寫的html檔案的路徑。

#pragma mark - lazy

- (UIWebView *)webview{

    if (!_webview) {

        _webview=[[UIWebViewalloc]initWithFrame:CGRectMake(0,200,self.view.bounds.size.width,300)];

        _webview.delegate =self;

        _webview.backgroundColor=[UIColorlightGrayColor];

        NSString *htmlPath = [[NSBundlemainBundle]pathForResource:@"index"ofType:@"html"];

        NSURL *localUrl = [[NSURLalloc]initFileURLWithPath:htmlPath];

        [_webview loadRequest:[NSURLRequestrequestWithURL:localUrl]];

    }

    return _webview;

}

3.2.

#pragma mark - UIWebViewDelegate

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

    //首先建立JSContext物件(此處通過當前webView的鍵獲取到jscontext)

   _context=[webView valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"];

    

    //第二種情況,js是通過物件呼叫的,我們假設js裡面有一個物件 testobject 在呼叫方法

    //首先建立我們新建類的物件,將他賦值給js的物件

    TestJSObject *testJO=[TestJSObjectnew];

    testJO.showPickerBlock = ^{

        [selfshowImagePicker];

    };

    _context[@"testobject"]=testJO;

}

 

到這裡,就已經大功告成了。。。文中打紅色的文字部分需要您仔細欣賞欣賞,,首先在TestJSObject.h中,我們聲明瞭一個block屬性,原因JS呼叫的方法實現在改類中,但是我們不能在這個類裡處理邏輯,那當然需要一個屬性回撥到控制器中咯,於是在實現中呼叫了block,然後在上面寫了block的實體,去呼叫

showImagePicker方法,然後你就可以處理了,,,,其實就是block最簡單的用法,,但是,,肯定有很多童鞋不瞭解。。哈哈,不耽誤。。下面附上控制器的所有程式碼,

//  Copyright © 2016年朱同海. All rights reserved.

//  本文主要介紹JS呼叫OC互動的方式

 

#import "ViewController.h"

#import <JavaScriptCore/JavaScriptCore.h>

#import "TestJSObject.h"

 

@interface ViewController () <UIWebViewDelegate,UIActionSheetDelegate>

{

    JSContext *_context;

}

@property (nonatomic,strong)UIWebView *webview;

@end

@implementation ViewController

- (void)viewDidLoad {

    [super viewDidLoad];

    self.view.backgroundColor = [UIColorcyanColor];

    [self.viewaddSubview:self.webview];

}

#pragma mark - lazy

- (UIWebView *)webview{

    if (!_webview) {

        _webview=[[UIWebViewalloc]initWithFrame:CGRectMake(0,200,self.view.bounds.size.width,300)];

        _webview.delegate =self;

        _webview.backgroundColor=[UIColorlightGrayColor];

        NSString *htmlPath = [[NSBundlemainBundle]pathForResource:@"index"ofType:@"html"];

        NSURL *localUrl = [[NSURLalloc]initFileURLWithPath:htmlPath];

        [_webview loadRequest:[NSURLRequestrequestWithURL:localUrl]];

    }

    return _webview;

}

#pragma mark - UIWebViewDelegate

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

    //首先建立JSContext物件(此處通過當前webView的鍵獲取到jscontext)

   _context=[webView valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"];

    

    //第二種情況,js是通過物件呼叫的,我們假設js裡面有一個物件 testobject 在呼叫方法

    //首先建立我們新建類的物件,將他賦值給js的物件

    TestJSObject *testJO=[TestJSObjectnew];

    testJO.showPickerBlock = ^{

        [self showImagePicker];

    };

    _context[@"testobject"]=testJO;

}

- (void)showImagePicker{

    NSLog(@"開始喚起相機");

    UIActionSheet *actionSheet = [[UIActionSheetalloc]

                                  initWithTitle:@"請選擇檔案來源"

                                  delegate:self

                                  cancelButtonTitle:@"取消"

                                  destructiveButtonTitle:nil

                                  otherButtonTitles:@"拍照",@"從手機相簿選擇",nil];

    [actionSheet showInView:self.view];

}

@end

 

 

4.上一些執行圖吧

  4.1:web view的介面圖;;

 

4.2,點選第一個按鈕,通過調

ZTHShowPicker方法,內部block的呼叫,喚起控制器中actionsheet。

4.3,點選最後兩個按鈕,,第一個傳遞訂單號,第二個傳遞訂單號和姓名,點了兩次,列印了兩次

 

5.關於帶多個引數的JS回撥,OC中對應方法的寫法:

 比如JS中定義了這個方法

 

 testobject.ZTHTestParameteroneAndParametertwo("1123425255","ZTH");那ZTHTestParameteroneAndParametertwo為方法名

那麼OC中方法名可以這麼寫:1和2都是可行的

 

1.- (void)ZTHTestParameterone:(NSString *)orderNumber AndParametertwo:(NSString *)name;

2.- (void)ZTHTestParameteroneAnd:(NSString *)orderNumber Parametertwo:(NSString *)name;

聰明的你看出來了,只要是OC的方法名去掉:(冒號)拼接起來後,,和JS的方法名一致,那麼都是會呼叫改方法的

 

千萬不能作死:說,我這麼拼也是我上面說的原理,那麼很遺憾的告訴你,不可以,你把And拆開了,是一個單詞,不識別(個人見解)

3.- (void)ZTHTestParameteroneA:(NSString *)orderNumberndParametertwo:(NSString *)name;

最後說兩句:這可能是JS互動中最好用的方法了,總結一下也就是我們在OC中定義一個遵守

JSExport協議的類,又定義了一個協議,宣告實現的方法和js中按鈕的點選事件方法名稱一致,用來一一對映。。最後在控制器中webview載入完畢之後,

 

 TestJSObject *testJO=[TestJSObjectnew];

    testJO.showPickerBlock = ^{

        [selfshowImagePicker];

    };

  _context[@"testobject"]=testJO;

當然OC內部肯定封裝了很多東西匹配他們,,這不用我們管,,最後我們看看JS檔案中的一個方法名

 

 testobject.ZTHpay();

原來是根據testobject這個物件聯絡起來的,

樓主語言能力不行,不知道有沒有繞暈你,但是你只要把demo跑一跑,問題就都能解決了。。當然你要是知道點h5的東西,那肯定更簡單咯

 

就先寫到這,回頭再完善,樓主其他文章裡有聯絡方式,比如這兩篇文章就有聯絡方式,如有不對的地方,歡迎指正。。想要demo的童鞋,可以加扣扣。。在下面的文章最後有。先好好上會班。

http://blog.csdn.net/horisea/article/details/51872619

http://blog.csdn.net/horisea/article/details/52025886

 

當然樓主也不是憑空就會的,本文參考連結,當時他說的是技術點,我把細節說的很細,結合下更好哦。

http://blog.csdn.net/lwjok2007/article/details/47058795

--------------------- 本文來自 -此夜微涼 的CSDN 部落格 ,全文地址請點選:https://blog.csdn.net/wanglei0918/article/details/62886734?utm_source=copy