OC與JS交互

要掌握iOS與JS交互阐滩,首先一定要掌握的就是,iOS的h5容器UIWebView和WKWebView,下面我們就分別來說說他們的用法和優(yōu)劣逾滥。
一、概述
??UIWebView自iOS2就有,WKWebView從iOS8才有寨昙,毫無疑問WKWebView將逐步取代UIWebView讥巡。WKWebView只能用代碼創(chuàng)建,而且自身就支持了右滑返回手勢(shì)allowsBackForwardNavigationGestures和加載進(jìn)度estimatedProgress等一些UIWebView不具備卻非常好用的屬性舔哪。通過簡單的測(cè)試即可發(fā)現(xiàn)UIWebView占用過多內(nèi)存欢顷。WKWebView網(wǎng)頁加載速度也有提升,但是并不像內(nèi)存那樣提升那么多捉蚤。下面列舉一些其它的優(yōu)勢(shì):

  • 更多的支持HTML5的特性
  • 官方宣稱的高達(dá)60fps的滾動(dòng)刷新率以及內(nèi)置手勢(shì)
  • 與Safari相同的JavaScript引擎
  • 將UIWebViewDelegate與UIWebView拆分成了14類與3個(gè)協(xié)議(官方文檔說明)
  • 另外用的比較多的抬驴,增加加載進(jìn)度屬性:estimatedProgress

UIWebView用法
1、加載網(wǎng)頁或本地文件

UIWebView *webView = [[UIWebView alloc] initWithFrame:[UIScreen mainScreen].bounds];
webView.delegate = self;
[self.view addSubview:webView];  
// 網(wǎng)頁url
// NSURL *url = [NSURL URLWithString:@"https://www.baidu.com"];
// 本地文件
NSString *path = [[NSBundle mainBundle] pathForResource:@"index" ofType:@"html"];
NSURL *url = [NSURL fileURLWithPath:path];
// 網(wǎng)絡(luò)請(qǐng)求
NSURLRequest *request =[NSURLRequest requestWithURL:url];
// 加載網(wǎng)頁
[self.webview loadRequest:request];

2缆巧、UIWebView的對(duì)象方法

// 加載Data數(shù)據(jù)創(chuàng)建一個(gè)webView
- (void)loadData:(NSData *)data MIMEType:(NSString *)MIMEType textEncodingName:(NSString *)encodingName baseURL:(NSURL *)baseURL
// 加載本地HTML創(chuàng)建一個(gè)webView
- (void)loadHTMLString:(NSString *)string baseURL:(NSURL *)baseURL
// 加載一個(gè)請(qǐng)求創(chuàng)建一個(gè)webView
- (void)loadRequest:(NSURLRequest *)request
// 刷新網(wǎng)頁
- (void)reload;
// 停止加載
- (void)stopLoading;
// 后退函數(shù)
- (void)goBack;
// 前進(jìn)函數(shù)
- (void)goForward;
// 執(zhí)行JS方法
- (nullable NSString *)stringByEvaluatingJavaScriptFromString:(NSString *)script;

3布持、UIWebView的屬性 :

// 代理屬性 重點(diǎn)需要知道代理方法的使用
@property (nullable, nonatomic, assign) id <UIWebViewDelegate> delegate;

// 這個(gè)是webView內(nèi)部的scrollView 只讀,但是利用這個(gè)屬性,設(shè)置scrollView的代理,就可以控制整個(gè)webView的滾動(dòng)事件
@property(nonatomic, readonly, strong) UIScrollView *scrollView;

// webView的請(qǐng)求,這個(gè)屬性一般在整個(gè)加載完成后才能拿到
@property (nullable, nonatomic, readonly, strong) NSURLRequest *request;

// 如果這個(gè)屬性為YES,才能后退
@property (nonatomic, readonly, getter=canGoBack) BOOL canGoBack;

// 如果這個(gè)屬性為YES,才能前進(jìn)
@property (nonatomic, readonly, getter=canGoForward) BOOL canGoForward;

// 這個(gè)屬性很好用,如果為YES證明webView還在加載數(shù)據(jù),所有數(shù)據(jù)加載完畢后,webView就會(huì)為No
@property (nonatomic, readonly, getter=isLoading) BOOL loading;

// YES代表網(wǎng)頁可以縮放,NO代表不可以縮放
@property (nonatomic) BOOL scalesPageToFit;

// 設(shè)置某些數(shù)據(jù)變?yōu)殒溄有问剑@個(gè)枚舉可以設(shè)置如電話號(hào)陕悬,地址题暖,郵箱等轉(zhuǎn)化為鏈接
@property (nonatomic) UIDataDetectorTypes dataDetectorTypes NS_AVAILABLE_IOS(3_0);

// 設(shè)置是否使用內(nèi)聯(lián)播放器播放視頻
@property (nonatomic) BOOL allowsInlineMediaPlayback NS_AVAILABLE_IOS(4_0); 

// 設(shè)置視頻是否自動(dòng)播放
@property (nonatomic) BOOL mediaPlaybackRequiresUserAction NS_AVAILABLE_IOS(4_0); 

// 設(shè)置音頻播放是否支持ari play功能
@property (nonatomic) BOOL mediaPlaybackAllowsAirPlay NS_AVAILABLE_IOS(5_0); 

// 設(shè)置是否將數(shù)據(jù)加載入內(nèi)存后渲染界面
@property (nonatomic) BOOL suppressesIncrementalRendering NS_AVAILABLE_IOS(6_0); 

// 設(shè)置用戶是否能打開keyboard交互
@property (nonatomic) BOOL keyboardDisplayRequiresUserAction NS_AVAILABLE_IOS(6_0); 

/* IOS7 */ 以后的新特性
// 這個(gè)屬性用來設(shè)置一種模式,當(dāng)網(wǎng)頁的大小超出view時(shí)捉超,將網(wǎng)頁以翻頁的效果展示芙委,枚舉如下:
@property (nonatomic) UIWebPaginationMode paginationMode NS_AVAILABLE_IOS(7_0);
typedef NS_ENUM(NSInteger, UIWebPaginationMode) { 
UIWebPaginationModeUnpaginated, //不使用翻頁效果 
UIWebPaginationModeLeftToRight, //將網(wǎng)頁超出部分分頁,從左向右進(jìn)行翻頁 
UIWebPaginationModeTopToBottom, //將網(wǎng)頁超出部分分頁狂秦,從上向下進(jìn)行翻頁 
UIWebPaginationModeBottomToTop, //將網(wǎng)頁超出部分分頁灌侣,從下向上進(jìn)行翻頁 
UIWebPaginationModeRightToLeft  //將網(wǎng)頁超出部分分頁,從右向左進(jìn)行翻頁 
};

// 這個(gè)屬性決定CSS的屬性分頁是可用還是忽略裂问。默認(rèn)是UIWebPaginationBreakingModePage 
@property (nonatomic) UIWebPaginationBreakingMode paginationBreakingMode NS_AVAILABLE_IOS(7_0);

// 設(shè)置每一頁的長度
@property (nonatomic) CGFloat pageLength NS_AVAILABLE_IOS(7_0);

// 設(shè)置每一頁的間距
@property (nonatomic) CGFloat gapBetweenPages NS_AVAILABLE_IOS(7_0);

// 獲取頁數(shù)
@property (nonatomic, readonly) NSUInteger pageCount NS_AVAILABLE_IOS(7_0);

4侧啼、相關(guān)代理協(xié)議

#pragma mark - UIWebViewDelegate
// 請(qǐng)求發(fā)送前都會(huì)調(diào)用該方法,返回NO則不處理這個(gè)請(qǐng)求,不加載網(wǎng)頁
- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType {
    NSLog(@"允許加載網(wǎng)頁");
    return YES;
}

// 請(qǐng)求發(fā)送之后開始接收響應(yīng)之前會(huì)調(diào)用這個(gè)方法
- (void)webViewDidStartLoad:(UIWebView *)webView {
    NSLog(@"開始加載網(wǎng)頁");
}

// 請(qǐng)求發(fā)送之后,并且服務(wù)器已經(jīng)返回響應(yīng)之后調(diào)用該方法
- (void)webViewDidFinishLoad:(UIWebView *)webView {
    NSLog(@"網(wǎng)頁加載完成");
}

// 網(wǎng)頁請(qǐng)求失敗則會(huì)調(diào)用該方法
- (void)webView:(UIWebView *)webView didFailLoadWithError:(NSError *)error {
    NSLog(@"網(wǎng)頁加載錯(cuò)誤時(shí)調(diào)用");
}

5、OC調(diào)用JS方法

OC調(diào)用JS函數(shù)主要通過下面方法:
- (nullable NSString )stringByEvaluatingJavaScriptFromString:(NSString )script;
例:
[self.webView stringByEvaluatingJavaScriptFromString:@"alertMobile()"];

調(diào)用這個(gè)方法需要在網(wǎng)頁加載完成之后堪簿,因?yàn)檫@個(gè)時(shí)候整個(gè)html頁面包括js/css已經(jīng)注入到webView中痊乾,此時(shí)調(diào)用方法才會(huì)有響應(yīng),相反網(wǎng)頁加載完成之前調(diào)用界面不會(huì)有任何響應(yīng)

6椭更、JS調(diào)用OC方法
??JS是不能執(zhí)行OC代碼的哪审,但是可以變相的執(zhí)行,JS可以將要執(zhí)行的操作封裝到網(wǎng)絡(luò)請(qǐng)求里面虑瀑,然后OC攔截這個(gè)請(qǐng)求湿滓,獲取URL里面的字符串解析即可,這里用到代理協(xié)議的如下方法:

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

有了上面的方法后舌狗,很顯然叽奥,想要JS調(diào)用OC我們就可以采用在按鈕點(diǎn)擊的后重定向一個(gè)URL,這個(gè)URL攜帶OC的方法名及參數(shù)信息痛侍,然后在這個(gè)方法中拿到對(duì)應(yīng)的URL朝氓,對(duì)URL進(jìn)行解析,提取對(duì)應(yīng)的方法名和參數(shù)信息,調(diào)用OC相應(yīng)的方法赵哲,從而實(shí)現(xiàn)了交互的可能

iiooss://showSendNumber_msg_?13300001111&這個(gè)周末去爬山

在這個(gè)URL中前面的"iiooss://"是URL的scheme待德,通過這個(gè)來提取我們關(guān)心的URL,對(duì)其他URL不做任何處理枫夺,后面就是OC方法和參數(shù)的信息了将宪,這里用"?"來分割分割方法名和參數(shù),"&"來分割多個(gè)參數(shù)筷屡,"_"用作OC方法名中冒號(hào)的替換涧偷。

例:
- (BOOL)webView:(UIWebView*)webView shouldStartLoadWithRequest:(NSURLRequest*)request navigationType:(UIWebViewNavigationType)navigationType {
    // 獲取請(qǐng)求路徑
    NSString *urlString = [[request URL] absoluteString];
    // 解碼
    urlString = [urlString stringByRemovingPercentEncoding];
    // 定義的協(xié)議
    NSString *scheme = @"iiooss://";
    if ([urlString hasPrefix:scheme]) {
        // 獲得協(xié)議后面的路徑
        NSString *subPath = [urlString substringFromIndex:scheme.length];
        if ([subPath containsString:@"?"]) {
            // 利用?切割路徑 分割方法與參數(shù)
            NSArray *components = [subPath componentsSeparatedByString:@"?"];

            // 方法名
            NSString *methodName = [components firstObject];
            methodName = [methodName stringByReplacingOccurrencesOfString:@"_" withString:@":"];

            // 參數(shù)
            NSString *parameter = [components lastObject];
            NSArray *params = [parameter componentsSeparatedByString:@"&"];
            
            /// 根據(jù)方法名與參數(shù)直接調(diào)用實(shí)現(xiàn)簸喂,
            /// 也可以考慮:- (id)performSelector:(SEL)aSelector;
            /// 或者NSInvocation
        }
        else
        {
            NSString *methodName = [subPath stringByReplacingOccurrencesOfString:@"_" withString:@":"];
            
            /// 根據(jù)方法名與參數(shù)直接調(diào)用實(shí)現(xiàn)毙死,
            /// 也可以考慮:- (id)performSelector:(SEL)aSelector;
            /// 或者NSInvocation
        }
    }
    return YES;
}

7、緩存
??盡量使用 GET 請(qǐng)求喻鳄,iOS 系統(tǒng) SDK 會(huì)自動(dòng)幫你做緩存扼倘。你需要的僅僅是設(shè)置下內(nèi)存緩存大小、磁盤緩存大小除呵、以及緩存路徑再菊。只要設(shè)置了這兩行代碼,基本就可滿足80%的緩存需求颜曾。

NSURLCache *urlCache = [[NSURLCache alloc] initWithMemoryCapacity:4*1024*1024 diskCapacity:20*1024*1024 diskPath:nil];
[NSURLCache setSharedURLCache:urlCache];

WKWebView的用法
Classes:

WKBackForwardList: 之前訪問過的 web 頁面的列表纠拔,可以通過后退和前進(jìn)動(dòng)作來訪問到。
WKBackForwardListItem: webview 中后退列表里的某一個(gè)網(wǎng)頁泛豪。
WKFrameInfo: 包含一個(gè)網(wǎng)頁的布局信息稠诲。
WKNavigation: 包含一個(gè)網(wǎng)頁的加載進(jìn)度信息。
WKNavigationAction: 包含可能讓網(wǎng)頁導(dǎo)航變化的信息诡曙,用于判斷是否做出導(dǎo)航變化臀叙。
WKNavigationResponse: 包含可能讓網(wǎng)頁導(dǎo)航變化的返回內(nèi)容信息,用于判斷是否做出導(dǎo)航變化价卤。
WKPreferences: 概括一個(gè) webview 的偏好設(shè)置劝萤。
WKProcessPool: 表示一個(gè) web 內(nèi)容加載池。
WKUserContentController: 提供使用 JavaScript post 信息和注射 script 的方法慎璧。
WKScriptMessage: 包含網(wǎng)頁發(fā)出的信息床嫌。
WKUserScript: 表示可以被網(wǎng)頁接受的用戶腳本。
WKWebViewConfiguration: 初始化 webview 的設(shè)置胸私。
WKWindowFeatures: 指定加載新網(wǎng)頁時(shí)的窗口屬性既鞠。

Protocols

WKNavigationDelegate: 提供了追蹤主窗口網(wǎng)頁加載過程和判斷主窗口和子窗口是否進(jìn)行頁面加載新頁面的相關(guān)方法。
WKScriptMessageHandler: 提供從網(wǎng)頁中收消息的回調(diào)方法盖文。
WKUIDelegate: 提供用原生控件顯示網(wǎng)頁的方法回調(diào)嘱蛋。

1、加載網(wǎng)頁或本地文件

 WKWebView *webView = [[WKWebView alloc] initWithFrame:[UIScreen mainScreen].bounds];
[self.view addSubview:webView];
// 網(wǎng)頁url
// NSURL *url = [NSURL URLWithString:@"https://www.baidu.com"];
// 網(wǎng)絡(luò)請(qǐng)求
// NSURLRequest *request =[NSURLRequest requestWithURL:url];
// 加載網(wǎng)頁
// [webView loadRequest:request];
    
// 創(chuàng)建url
NSString *path = [[NSBundle mainBundle] pathForResource:@"index" ofType:@"html"];
// 創(chuàng)建URL
NSURL *url = [NSURL fileURLWithPath:path];
// 加載文件
[webView loadFileURL:url allowingReadAccessToURL:url];
self.webView = webView;

2、WKWebView的對(duì)象方法

// 這是加載網(wǎng)頁最常用的一種方式洒敏,通過一個(gè)網(wǎng)頁URL來加載一個(gè)WKWebView龄恋,這個(gè)URL可以是遠(yuǎn)程的也可以是本地的,例如我加載百度的主頁
- (nullable WKNavigation *)loadRequest:(NSURLRequest *)request;

// 根據(jù)一個(gè)文件,加載一個(gè)WKWebView
- (nullable WKNavigation *)loadFileURL:(NSURL *)URL allowingReadAccessToURL:(NSURL *)readAccessURL NS_AVAILABLE(10_11, 9_0);

// 這個(gè)方法需要將html文件讀取為字符串從而加載為WKWebView凶伙,其中baseURL是我們自己設(shè)置的一個(gè)路徑郭毕,用于尋找html文件中引用的圖片等素材。
- (nullable WKNavigation *)loadHTMLString:(NSString *)string baseURL:(nullable NSURL *)baseURL;

// 這個(gè)方式使用的比較少函荣,但也更加自由显押,其中data是文件數(shù)據(jù),MIMEType是文件類型傻挂,characterEncodingName是編碼類型乘碑,baseURL是素材資源路徑
- (nullable WKNavigation *)loadData:(NSData *)data MIMEType:(NSString *)MIMEType characterEncodingName:(NSString *)characterEncodingName baseURL:(NSURL *)baseURL NS_AVAILABLE(10_11, 9_0);

3、WKWebView的屬性

// UIWebView 中會(huì)自動(dòng)保存Cookie金拒,如果登錄了一次下次再次進(jìn)入的時(shí)候,會(huì)記住登錄狀態(tài)
// 在WKWebView中兽肤,新增一個(gè)configuration屬性,  configuration 讓W(xué)KWebView知道登錄狀態(tài),
// configuration 可以通過已有的Cookie進(jìn)行設(shè)置绪抛,也可以通過保存上一次的configuration進(jìn)行設(shè)置
// WKWebViewConfiguration類中也有一些相應(yīng)的屬性
@property (nonatomic, readonly, copy) WKWebViewConfiguration *configuration;

// WKWebView中,加入了網(wǎng)站導(dǎo)航的概念,這個(gè)對(duì)象決定主框架導(dǎo)航加載方法協(xié)議资铡。
@property (nullable, nonatomic, weak) id <WKNavigationDelegate> navigationDelegate;

// WKWebView中,加入了網(wǎng)站窗口的概念,這個(gè)對(duì)象決了webView窗口的一些方法協(xié)議。
@property (nullable, nonatomic, weak) id <WKUIDelegate> UIDelegate;

// WKWebView中,加入了網(wǎng)站列表的概念,這個(gè)WEBBackForwardList對(duì)象是以前在Web視圖訪問的網(wǎng)頁幢码,可以通過去后退或前進(jìn)
@property (nonatomic, readonly, strong) WKBackForwardList *backForwardList;

4笤休、WKWebView的代理方法

/**
 *  web內(nèi)容處理中斷時(shí)會(huì)觸發(fā)
 *  當(dāng) WKWebView 總體內(nèi)存占用過大,頁面即將白屏的時(shí)候症副,系統(tǒng)會(huì)調(diào)用上面的回調(diào)函數(shù)店雅,我們?cè)谠摵瘮?shù)里執(zhí)行[webView reload](這個(gè)時(shí)候 webView.URL 取值尚不為 nil)解決白屏問題。
 */
- (void)webViewWebContentProcessDidTerminate:(WKWebView *)webView {
    NSLog(@"webViewWebContentProcessDidTerminate:  當(dāng)Web視圖的網(wǎng)頁內(nèi)容被終止時(shí)調(diào)用瓦糕。");
}

/**
 *  頁面加載完成底洗。 等同于UIWebViewDelegate: - webViewDidFinishLoad:
 *
 *  @param webView
 *  @param navigation
 */
- (void)webView:(WKWebView *)webView didFinishNavigation:(null_unspecified WKNavigation *)navigation {
    [UIApplication sharedApplication].networkActivityIndicatorVisible = NO;
    NSLog(@"webView:didFinishNavigation:  響應(yīng)渲染完成后調(diào)用該方法   webView : %@  -- navigation : %@  \n\n",webView,navigation);
}

/**
 *  準(zhǔn)備加載頁面。等同于UIWebViewDelegate: - webView:shouldStartLoadWithRequest:navigationType
 *
 *  @param webView
 *  @param navigation
 */
- (void)webView:(WKWebView *)webView didStartProvisionalNavigation:(null_unspecified WKNavigation *)navigation {
    [UIApplication sharedApplication].networkActivityIndicatorVisible = YES;
    NSLog(@"webView:didStartProvisionalNavigation:  開始請(qǐng)求  \n\n");
}

/**
 *  內(nèi)容開始加載. 等同于UIWebViewDelegate: - webViewDidStartLoad:
 *
 *  @param webView
 *  @param navigation
 */
- (void)webView:(WKWebView *)webView didCommitNavigation:(WKNavigation *)navigation {
    NSLog(@"webView:didCommitNavigation:   響應(yīng)的內(nèi)容到達(dá)主頁面的時(shí)候響應(yīng),剛準(zhǔn)備開始渲染頁面應(yīng)用 \n\n");
}

/**
 *  頁面加載失敗時(shí)調(diào)用
 */
- (void)webView:(WKWebView *)webView didFailProvisionalNavigation:(WKNavigation *)navigation withError:(NSError *)error {
    // 類似 UIWebView 的- webView:didFailLoadWithError:
    NSLog(@"webView:didFailProvisionalNavigation:withError: 啟動(dòng)時(shí)加載數(shù)據(jù)發(fā)生錯(cuò)誤就會(huì)調(diào)用這個(gè)方法咕娄。  \n\n");
}

/**
 *  頁面加載失敗亥揖。 等同于UIWebViewDelegate: - webView:didFailLoadWithError:
 *
 *  @param webView
 *  @param navigation
 *  @param error      
 */
- (void)webView:(WKWebView *)webView didFailNavigation:(WKNavigation *)navigation withError:(NSError *)error {
    NSLog(@"webView:didFailNavigation: 當(dāng)一個(gè)正在提交的頁面在跳轉(zhuǎn)過程中出現(xiàn)錯(cuò)誤時(shí)調(diào)用這個(gè)方法。  \n\n");
}

/**
 *  根據(jù)webView圣勒、navigationAction相關(guān)信息決定這次跳轉(zhuǎn)是否可以繼續(xù)進(jìn)行,這些信息包含HTTP發(fā)送請(qǐng)求费变,如頭部包含User-Agent,Accept,refer
 *  在發(fā)送請(qǐng)求之前,決定是否跳轉(zhuǎn)的代理
 *  @param webView
 *  @param navigationAction
 *  @param decisionHandler
 */
- (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler {
    NSLog(@"請(qǐng)求前會(huì)先進(jìn)入這個(gè)方法  webView:decidePolicyForNavigationActiondecisionHandler: %@   \n\n  ",navigationAction.request);
    decisionHandler(WKNavigationActionPolicyAllow);
}

/**
 *  這個(gè)代理方法表示當(dāng)客戶端收到服務(wù)器的響應(yīng)頭圣贸,根據(jù)response相關(guān)信息挚歧,可以決定這次跳轉(zhuǎn)是否可以繼續(xù)進(jìn)行。
 *  在收到響應(yīng)后吁峻,決定是否跳轉(zhuǎn)的代理
 *  @param webView
 *  @param navigationResponse
 *  @param decisionHandler
 */
- (void)webView:(WKWebView *)webView decidePolicyForNavigationResponse:(WKNavigationResponse *)navigationResponse decisionHandler:(void (^)(WKNavigationResponsePolicy))decisionHandler {
    NSLog(@"返回響應(yīng)前先會(huì)調(diào)用這個(gè)方法  并且已經(jīng)能接收到響應(yīng)webView:decidePolicyForNavigationResponse:decisionHandler: Response?%@  \n\n",navigationResponse.response);
    decisionHandler(WKNavigationResponsePolicyAllow);
}

/**
 *  這個(gè)代理是服務(wù)器redirect時(shí)調(diào)用
 *  接收到服務(wù)器跳轉(zhuǎn)請(qǐng)求的代理
 *  @param webView
 *  @param navigation
 */
- (void)webView:(WKWebView *)webView didReceiveServerRedirectForProvisionalNavigation:(WKNavigation *)navigation {
    NSLog(@"webView:didReceiveServerRedirectForProvisionalNavigation: 重定向的時(shí)候就會(huì)調(diào)用  \n\n");
}

WKScriptMessageHandler:必須實(shí)現(xiàn)的函數(shù)滑负,是APP與js交互在张,提供從網(wǎng)頁中收消息的回調(diào)方法

// 是js與APP交互,提供從網(wǎng)頁中收消息的回調(diào)方法
- (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message;

與JS的alert矮慕、confirm帮匾、prompt交互,我們希望用自己的原生界面痴鳄,而不是JS的瘟斜,就可以使用這個(gè)代理類來實(shí)現(xiàn)。

// 新開一個(gè)WebView
- (WKWebView *)webView:(WKWebView *)webView createWebViewWithConfiguration:(WKWebViewConfiguration *)configuration forNavigationAction:(WKNavigationAction *)navigationAction windowFeatures:(WKWindowFeatures *)windowFeatures;
// prompt 輸入框
- (void)webView:(WKWebView *)webView runJavaScriptTextInputPanelWithPrompt:(NSString *)prompt defaultText:(nullable NSString *)defaultText initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(NSString * __nullable result))completionHandler;
// confirm 確認(rèn)框
- (void)webView:(WKWebView *)webView runJavaScriptConfirmPanelWithMessage:(NSString *)message initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(BOOL result))completionHandler;
// alert 警告框
- (void)webView:(WKWebView *)webView runJavaScriptAlertPanelWithMessage:(NSString *)message initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(void))completionHandler;

5痪寻、網(wǎng)頁導(dǎo)航刷新有關(guān)函數(shù)

@property (nonatomic, readonly) BOOL canGoBack;
@property (nonatomic, readonly) BOOL canGoForward;
- (WKNavigation *)goBack;
- (WKNavigation *)goForward;
- (WKNavigation *)reload;
- (WKNavigation *)reloadFromOrigin; // 增加的函數(shù)
- (WKNavigation *)goToBackForwardListItem:(WKBackForwardListItem *)item; // 增加的函數(shù)
- (void)stopLoading;

reloadFromOrigin會(huì)比較網(wǎng)絡(luò)數(shù)據(jù)是否有變化螺句,沒有變化則使用緩存,否則從新請(qǐng)求橡类。
goToBackForwardListItem:比向前向后更強(qiáng)大蛇尚,可以跳轉(zhuǎn)到某個(gè)指定歷史頁面

6、一些常用屬性

allowsBackForwardNavigationGestures:BOOL類型猫态,是否允許左右劃手勢(shì)導(dǎo)航佣蓉,默認(rèn)不允許
estimatedProgress:加載進(jìn)度披摄,取值范圍0~1
title:頁面title
scrollView.scrollEnabled:是否允許上下滾動(dòng)亲雪,默認(rèn)允許
backForwardList:WKBackForwardList類型,訪問歷史列表疚膊,可以通過前進(jìn)后退按鈕訪問义辕,或者通過goToBackForwardListItem函數(shù)跳到指定頁面

7、JS調(diào)用OC

index.html:
// 內(nèi)聯(lián)事件寓盗、腳本事件或DOM事件調(diào)用此函數(shù)
function onClickButton() {
    // JS通知WKWebView
    window.webkit.messageHandlers.senderModel.postMessage("參數(shù)");
}
 // webview的相關(guān)配置
WKWebViewConfiguration *config = [WKWebViewConfiguration new];
// 初始化偏好設(shè)置屬性:preferences
config.preferences = [WKPreferences new];
// 默認(rèn)值中的最小字體大小是0
config.preferences.minimumFontSize = 10;
// 是否支持JavaScript
config.preferences.javaScriptEnabled = YES;
// 不通過用戶交互灌砖,是否可以打開窗口
config.preferences.javaScriptCanOpenWindowsAutomatically = NO;
    
// js配置---通過JS與webView內(nèi)容交互
config.userContentController = [WKUserContentController new];
// js通過senderModel來調(diào)用
[config.userContentController addScriptMessageHandler:self name:@"senderModel"];

WKWebView *webView = [[WKWebView alloc]initWithFrame:self.view.bounds configuration:config];
NSURL *path = [[NSBundle mainBundle] URLForResource:@"index" withExtension:@"html"];
webView.UIDelegate = self;
webView.navigationDelegate = self;
[webView loadRequest:[NSURLRequest requestWithURL:path]];
[self.view addSubview:webView];
self.webView = webView;
響應(yīng):
- (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message {
    NSLog(@"方法名:%@", message.name);
    NSLog(@"參數(shù):%@", message.body);
    // 方法名
    NSString *methods = [NSString stringWithFormat:@"%@:", message.name];

    /// 根據(jù)方法名與參數(shù)直接調(diào)用實(shí)現(xiàn),
    /// 也可以考慮:- (id)performSelector:(SEL)aSelector;參數(shù)以字面量對(duì)象形式
    /// 或者NSInvocation
}

8傀蚌、OC調(diào)用JS

oc調(diào)用js就特別簡單了基显,只需WKWebView調(diào)用下面方法即可。
NSString *jsActionStr = [NSString stringWithFormat:@"actionName('%@')",  @"參數(shù)"];
[self.webView evaluateJavaScript:jsActionStr completionHandler:^(id _Nullable data, NSError * _Nullable error) {
      if (error) {
             NSLog(@"錯(cuò)誤:%@", error.localizedDescription);
      }
}];
響應(yīng):
index.html:
// 函數(shù)
function actionName(params) {
                document.getElementById('spanId').innerHTML = params;
            }

9善炫、WKUserScript JS注入
??在WebKit框架中撩幽,我們還可以預(yù)先添加JS方法,供其ta人員調(diào)用箩艺。WKUserScript就是幫助我們完成JS注入的類窜醉,它能幫助我們?cè)陧撁嫣畛淝盎騤s填充完成后調(diào)用。
WKUserScript核心方法:

- (instancetype)initWithSource:(NSString *)source injectionTime:(WKUserScriptInjectionTime)injectionTime forMainFrameOnly:(BOOL)forMainFrameOnly;

在WKUserScriptInjectionTime枚舉中有兩個(gè)狀態(tài):

1. WKUserScriptInjectionTimeAtDocumentStart:js加載前執(zhí)行艺谆。
2. WKUserScriptInjectionTimeAtDocumentEnd:js加載后執(zhí)行榨惰。

10、歷史記錄

// 查詢歷史記錄
WKBackForwardList *backForwardList = self.webView.backForwardList;

暫時(shí)先這么多吧静汤,以后想起什么再補(bǔ)充琅催,都是些簡單的應(yīng)用居凶,具體實(shí)現(xiàn)根據(jù)具體情況而定,寫程序不要寫死藤抡,靈活應(yīng)用方為上策排监,這里呢也算一個(gè)小的總結(jié)吧,避免重復(fù)造輪子杰捂。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末舆床,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子嫁佳,更是在濱河造成了極大的恐慌挨队,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,542評(píng)論 6 504
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件蒿往,死亡現(xiàn)場(chǎng)離奇詭異盛垦,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)瓤漏,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,822評(píng)論 3 394
  • 文/潘曉璐 我一進(jìn)店門腾夯,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人蔬充,你說我怎么就攤上這事蝶俱。” “怎么了饥漫?”我有些...
    開封第一講書人閱讀 163,912評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵榨呆,是天一觀的道長。 經(jīng)常有香客問我庸队,道長积蜻,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,449評(píng)論 1 293
  • 正文 為了忘掉前任彻消,我火速辦了婚禮竿拆,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘宾尚。我一直安慰自己丙笋,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,500評(píng)論 6 392
  • 文/花漫 我一把揭開白布央勒。 她就那樣靜靜地躺著不见,像睡著了一般。 火紅的嫁衣襯著肌膚如雪崔步。 梳的紋絲不亂的頭發(fā)上稳吮,一...
    開封第一講書人閱讀 51,370評(píng)論 1 302
  • 那天,我揣著相機(jī)與錄音井濒,去河邊找鬼灶似。 笑死列林,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的酪惭。 我是一名探鬼主播希痴,決...
    沈念sama閱讀 40,193評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼春感!你這毒婦竟也來了砌创?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,074評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤鲫懒,失蹤者是張志新(化名)和其女友劉穎嫩实,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體窥岩,經(jīng)...
    沈念sama閱讀 45,505評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡甲献,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,722評(píng)論 3 335
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了颂翼。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片晃洒。...
    茶點(diǎn)故事閱讀 39,841評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖朦乏,靈堂內(nèi)的尸體忽然破棺而出球及,到底是詐尸還是另有隱情,我是刑警寧澤集歇,帶...
    沈念sama閱讀 35,569評(píng)論 5 345
  • 正文 年R本政府宣布桶略,位于F島的核電站语淘,受9級(jí)特大地震影響诲宇,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜惶翻,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,168評(píng)論 3 328
  • 文/蒙蒙 一姑蓝、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧吕粗,春花似錦纺荧、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,783評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至议泵,卻和暖如春占贫,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背先口。 一陣腳步聲響...
    開封第一講書人閱讀 32,918評(píng)論 1 269
  • 我被黑心中介騙來泰國打工型奥, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留瞳收,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 47,962評(píng)論 2 370
  • 正文 我出身青樓厢汹,卻偏偏與公主長得像螟深,于是被迫代替她去往敵國和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子烫葬,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,781評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容

  • 隨著H5技術(shù)的興起界弧,在iOS開發(fā)過程中,難免會(huì)遇到原生應(yīng)用需要和H5頁面交互的問題搭综。其中會(huì)涉及方法調(diào)用及參數(shù)傳值等...
    Chris_js閱讀 3,068評(píng)論 1 8
  • iOS中用來加載網(wǎng)頁设凹,有兩個(gè)控件UIWebView(iOS8之前)舰讹,WKWebView(iOS8誕生)。此篇博文暫...
    墨痕未干閱讀 1,463評(píng)論 7 21
  • 前言 隨著H5的強(qiáng)大闪朱,hybrid app已經(jīng)成為當(dāng)前互聯(lián)網(wǎng)的大方向月匣,單純的native app和web app在...
    獨(dú)酌丿紅顏閱讀 1,387評(píng)論 3 8
  • 進(jìn)入15年以后,在我們天朝越來越流行混編奋姿!尤其是騰訊的 變態(tài)APP微信小程序一出锄开,撐起了混編的半邊天! 廢話不多說...
    白水灬煮一切閱讀 1,235評(píng)論 0 2
  • 端莊的人總是端莊称诗。 -----針灸科的一位“老校長”病人
    嘉里f閱讀 59評(píng)論 0 0