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