1. 程式人生 > >iOS webView的高階用法之JS互動,js與oc的相互呼叫(JavaScriptCore)

iOS webView的高階用法之JS互動,js與oc的相互呼叫(JavaScriptCore)

重要的事情放前面 github地址:https://github.com/horisea/JSCallOCTest   歡迎star

前言:說起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;

注意:如果上面不行,也可以這麼命名

3.- (void)ZTHTestParameteroneAndParametertwo:(NSString *)orderNumber    :(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/lwjok2007/article/details/47058795

如果你喜歡這篇文章,或者有任何疑問,可以掃描第一個二維碼,加樓主好友哦

也可以掃第二個二維碼,進qq群。這裡有很多生活,職業,技術相關的文章哦。歡迎您的到來。

微訊號:                                             群

相關推薦

iOS js oc相互呼叫JavaScriptCore

從iOS7開始 蘋果公佈了JavaScriptCore.framework 它使得JS與OC的互動更加方便了。 下面我們就簡單瞭解一下這個框架 首先我匯入framework 方法如下 點選Linked Frameworks and Libraries 的

iOS webView高階用法JS互動jsoc相互呼叫JavaScriptCore

重要的事情放前面 github地址:https://github.com/horisea/JSCallOCTest   歡迎star 前言:說起JS互動,很多童鞋會黯然色變,感覺很高深的樣子。大部分小夥伴只知道一種,哪一種我也說說吧。    1.在webView中將要

iOSJSOC互相呼叫--MessageHandler

使用WKWebView的時候,如果想要實現JS呼叫OC方法,除了攔截URL之外,還有一種簡單的方式。那就是利用WKWebView的新特性MessageHandler來實現JS呼叫原生方法。 MessageHandler 是什麼? WKWebView 初始

iOSJSOC互相呼叫--Cordova詳解+實戰

扯兩句,可以跳過 由於專案中Cordova相關功能一直是同事在負責,所以也沒有仔細的去探究Cordova到底是怎麼使用的,又是如何實現JS 與 OC 的互動。所以我基本上是從零開始研究和學習Cordova的使用,從上篇在官網實現命令列建立工程,到工程執行起來,

iOSJSOC互相呼叫--JavaScriptCore

前面講完攔截URL的方式實現JS與OC互相呼叫,終於到JavaScriptCore了。它是從iOS7開始加入的,用 Objective-C 把 WebKit 的 JavaScript 引擎封裝了一下,提供了簡單快捷的方式與JavaScript互動。 關於JavaScriptCore的使用有兩篇很好的文章:N

iOSJSOC互相呼叫-->WKWebView + WebViewJavascriptBridge

上一篇文章介紹了UIWebView 如何通過WebViewJavascriptBridge 來實現JS 與OC 的互相呼叫,這一篇來介紹一下WKWebView 又是如何通過WebViewJavascriptBridge 來實現JS 與OC 的互相呼叫的。WKWebView

iOSJSOC互相呼叫--Cordova 基礎

Cordova 簡介 在介紹Cordova之前,必須先提一下PhoneGap。PhoneGap 是Nitobi軟體公司2008年推出的一個框架,旨在彌補web 和iOS 之間的不足,使得web 和 iPhone SDK 之間的互動更容易。後來又加入了Android SDK 和BlackBerry SDK,再

java 核心編程——IO流字符流和字節流相互轉換

red amr nbsp main 字符輸入 txt not stat args 1.為什麽字符流和字節流需要轉換?   這是因為有一些時候系統給你提供的只有字節流,比如說System.in標準輸入流。就是字節流。你想從他那裏得到用戶在鍵盤上的輸入,只能是以轉換流將它轉換為

JS使用WebSocket實現Java圖形介面swing進行通訊

背景:做專案的時候有過這樣的一個需求,在訪問某個網頁的時候進行登入,需要瀏覽器獲取電腦的硬體資源,但是通過瀏覽器直接讀取的方式有些不便,所以想到使用Java開發一個圖形應用介面的程式讀取電腦程式通過socket通訊傳輸給html頁面用於驗證。 寫在前面:在Java伺服器這端

SpringMVCWeb引入靜態資源規範請求字尾

1.Spring3+以上的版本可以直接在springmvc-servlet.xml裡面直接設定:     <mvc:annotation-driven />        <mvc

IOS中如何在多層介面之間顯示隱藏標籤欄UITabBar

在做專案的時候,遇到了一個難題,使用hidesBottomWhenPushed=YES屬性設定,可以讓本級介面及其以後介面都隱藏,但是根據專案 需求,在第4層是需要顯示標籤欄的。 於是想了很多的辦法,每個要顯示的push的介面前都加了hidesBottomWhenPushe

【黑馬程式設計師】Objective-C語言學習筆記物件的建立、使用和方法呼叫

--------------------------------------------IOS期待與您交流!-------------------------------------------- 一、物件的建立 物件是由類建立,我們使用上一文章用到的類來建立物件。 說明:

iOS webView高階用法JS互動

前言:說起JS互動,很多童鞋會黯然色變,感覺很高深的樣子。大部分小夥伴只知道一種,哪一種我也說說吧。    1.在webView中將要請求的時候,攔截URL,進行重定向,然而該場景實用有限,網上資料也很多下面說說另一種互動方式。 - (BOOL)webView:(UIWe

iOS網頁JS互動看我就夠了

隨著移動APP的快速迭代開發趨勢,越來越多的APP中嵌入了html網頁,但在一些大中型APP中,尤其是電商類APP,html頁面已經不僅僅滿足展示功能,這時html要求能與原生語言進行互動、相互傳值。比如攜程APP中一個熱門景點的網頁中,點選某個景點,

iOSJS互動OC呼叫JS方法JS呼叫OC方法URL解碼

 首先 iOS7開始 蘋果公佈了JavaScriptCore.framework 它使得JS與OC的互動更加方便了。  第一步:匯入framework  OC 呼叫JS方法 :(一句話即可) -(void)webViewDidFinishLoad:(UIWebV

ios 中pickerView用法國旗選擇

spa copy interface option sin source 出現 color import QRViewController控制器 // // QRViewController.m // #import "QRViewController.h" #imp

qtjs互動並在百度地圖上繪製軌跡

前言: 獲得了照片的GPS資訊後,我們現在要做的就是把GPS資訊傳入JS中,然後通過百度地圖API將軌跡繪製出來。 一:在程式頁面載入地圖 qt5.6及之後取消了QWebkits,轉為使用QWebEngine. 在qt5.6的額ui設計師介面中,並不能直

Python高階用法yield關鍵字

很多blog裡面說,yield關鍵字和return關鍵字非常類似。只不過yield關鍵字更復雜一點。 我們都知道,return就是返回一個值,一般位於函式的末尾(或者說,作為函式結束的標誌)。只要函式執行到return,那麼這個函式的這次呼叫就結束了。 yield並不是這

Androidjs互動帶進度條的載入H5頁面

private void initWebView() { WebSettings settings = wvResumeDetail.getSettings(); //支援JavaScript指令碼語言 settings

Fiddler高階用法url對映請求

問題場景:     已釋出線上APP出現介面錯誤,如何測試線上APP訪問本地請求?     已釋出線上H5頁面,靜態資源或js除錯,如何對映本地js? 一般解決方案:     猜測(一般明顯問題)、     找到原發布包,修改請求資源url重新打包測試。需要前後端協調配合,耗時費力。 fiddler對映響應: