iOS之WKWebView、UIWebView、WebViewJavascriptBridge三方框架

目錄
    1. WKWebView
    2. UIWebView(javascriptcore.framework)
    3. 三方WebViewJavascriptBridge框架
1. WKWebView
:UIView  

  iOS8后推出
  Safari瀏覽器(iPhone、mac)都是基于WKWebView 實現的。
  相比WebView更省內存。

1.1 使用詳解

#import <WebKit/WebKit.h>    
<WKScriptMessageHandler,WKUIDelegate,WKNavigationDelegate>
    
/**
 初始化UI
 */
-(void)setupUI{
    [self.view addSubview:self.webView];
}
/**
 設置URL,并加載
 */
-(void)setUrlStr:(NSString *)urlStr{
    _urlStr=urlStr;
    
    [self.webView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:urlStr]]];
}


-(WKWebView *)webView{
    if(!_webView){
        // 創建WKWebView
        _webView=[[WKWebView alloc]initWithFrame:CGRectZero configuration:({
            // 創建配置類
            WKWebViewConfiguration *config=[WKWebViewConfiguration new];
            config;
        })];
        [_webView setFrame:CGRectMake(0, C_NavBarAndStatusBarHeight, C_ScreenWidth, C_ScreenHeight-C_NavBarAndStatusBarHeight)];
        // 設置dele <WKUIDelegate,WKNavigationDelegate>
        [_webView setUIDelegate:self];
        [_webView setNavigationDelegate:self];
        
        // 設置其他
        [_webView setBackgroundColor:[UIColor whiteColor]];
        [_webView.scrollView setShowsVerticalScrollIndicator:false];
        [_webView.scrollView setShowsHorizontalScrollIndicator:false];
    }
    return _webView;
}

常用屬性/方法

獲取常用信息

    // 標題(readOnly)
    NSString *title=webView.title;
    // url地址(readOnly)
    NSURL *URL=webView.URL;  
    // 是否正在加載(readOnly)
    BOOL loading=webView.isLoading 
    // 加載進度(readOnly)
    double estimatedProgress=webView.estimatedProgress;  
    // 是否加密(readOnly)
    BOOL hasOnlySecureContent=webView.hasOnlySecureContent; 
    // scrollView(readOnly)
    UIScrollView *scrollView=webView.scrollView;
加載請求

    // loadRequest
    [webView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:@"url"]]];
    // 加載fileURL
    [webView loadFileURL:[NSURL URLWithString:@""] allowingReadAccessToURL:[NSURL URLWithString:@""]];
    // 加載data
    [webView loadData:[NSData data] MIMEType:@"" characterEncodingName:@"" baseURL:[NSURL URLWithString:@""]];
    // 加載本地html
    NSString *urlStr=[[NSBundle mainBundle]pathForResource:@"index.html" ofType:nil];
    [webView loadHTMLString:[NSString stringWithContentsOfFile:urlStr encoding:NSUTF8StringEncoding error:nil] baseURL:[NSURL URLWithString:urlStr]];
重新加載
    // 重新加載
    [webView reload];
    // 重新加載初始網址
    [webView reloadFromOrigin];
    // 停止加載
    [webView stopLoading];

預覽
    // 設置 是否允許預覽鏈接(默認:true)
    [webView setAllowsLinkPreview:true];
向前向后

    // 設置 是否支持手勢前進后退(默認:false)
    [webView setAllowsBackForwardNavigationGestures:true];

    // 是否允許向后(readOnly)
    BOOL canGoBack=webView.canGoBack;
    // 是否允許向前(readOnly)
    BOOL canGoForward=webView.canGoForward;
    // 向后
    [webView goBack];
    // 向前
    [webView goForward];

    // 獲取頁面前進后退列表(readOnly)
    WKBackForwardList *list=webView.backForwardList;
    // 當前(readOnly)
    WKBackForwardListItem *item=list.currentItem;
    // 前一個(readOnly)
    WKBackForwardListItem *itemForward=list.forwardItem;
    // 后一個(readOnly)
    WKBackForwardListItem *itemBack=list.backItem;
    // 后列表(readOnly)
    NSArray *backList=list.backList;
    // 前列表(readOnly)
    NSArray *forwardList=list.forwardList;

    // 根據下標獲取指定頁
    WKBackForwardListItem *item=[list itemAtIndex:0];
    // 前進或后退到指定頁
    [webView goToBackForwardListItem:item];

    // (readOnly)
    NSURL *URL=item.URL;
    NSURL *initialURL=item.initialURL;
    NSString *title=item.title;

dele

【OC調用js中的方法】
  [webView evaluateJavaScript:@"helloWorld" completionHandler:^(id _Nullable obj, NSError * _Nullable error) {}];


【js調用OC中的方法】
-(void)viewWillAppear:(BOOL)animated{
    [super viewWillAppear:animated];
    // 首先設置交互(js調用OC),設置dele
    [self.webView.configuration.userContentController addScriptMessageHandler:self name:@"helloWorld"];
}
-(void)viewWillDisappear:(BOOL)animated{
    [super viewWillDisappear:animated];
    // 最后移除交互
    [self.webView.configuration.userContentController removeAllUserScripts];
}

#pragma mark dele <WKScriptMessageHandler>        
// js調用OC方法后調用(required)
-(void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message{
    NSLog(@"js調用OC方法后調用");
    SEL selector = NSSelectorFromString([NSString stringWithFormat:@"%@:",message.name]);
    if ([self respondsToSelector:selector]) {
        [self performSelector:selector withObject:message.body];
    }
}
// js中這樣調用 window.webkit.messageHandlers.helloWorld.postMessage({body: 'hello world!'});
-(void)helloWorld:(NSDictionary *)dic{
    NSLog(@"");
}
#pragma mark dele<WKUIDelegate>    都為可選方法

// =============== alert、confirm、prompt

// js中調用alert后調用
-(void)webView:(WKWebView *)webView runJavaScriptAlertPanelWithMessage:(NSString *)message initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(void))completionHandler{
    NSLog(@"js中調用alert");
    /*
     message:alert中的內容
     */
    completionHandler();
}
// js中調用confirm后調用
-(void)webView:(WKWebView *)webView runJavaScriptConfirmPanelWithMessage:(NSString *)message initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(BOOL))completionHandler{
    NSLog(@"js中調用confirm");
    /*
     message:confirm中的內容
     */
    // true確認,false取消
    completionHandler(true);
}
// js中調用prompt后調用
-(void)webView:(WKWebView *)webView runJavaScriptTextInputPanelWithPrompt:(NSString *)prompt defaultText:(NSString *)defaultText initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(NSString * _Nullable))completionHandler{
    NSLog(@"js中調用prompt");
    /*
     prompt:標題
     defaultText:默認文本
     */
    // 文本框中的填寫內容
    completionHandler(@"你好");
}


// =============== 預覽

// 是否允許預覽(長安鏈接時觸發預覽)
- (BOOL)webView:(WKWebView *)webView shouldPreviewElement:(WKPreviewElementInfo *)elementInfo{
    /*
     elementInfo.linkURL    預覽的url
     */
    return true;
}
// 觸發預覽后調用,返回預覽VC
- (nullable UIViewController *)webView:(WKWebView *)webView previewingViewControllerForElement:(WKPreviewElementInfo *)elementInfo defaultActions:(NSArray<id <WKPreviewActionItem>> *)previewActions{
    return [UIViewController new];
}
// 觸發pop操作預覽消失時調用
- (void)webView:(WKWebView *)webView commitPreviewingViewController:(UIViewController *)previewingViewController{
    NSLog(@"預覽取消時調用");
}


// =============== 創建/關閉

// 創建新的webView后回調,調用window.open()創建新窗口后觸發
-(WKWebView *)webView:(WKWebView *)webView createWebViewWithConfiguration:(WKWebViewConfiguration *)configuration forNavigationAction:(WKNavigationAction *)navigationAction windowFeatures:(WKWindowFeatures *)windowFeatures{
    
    // 必須使用configuration
    return [[WKWebView alloc]initWithFrame:CGRectZero configuration:configuration];
}
// 關閉當前webView后調用,調用window.close()觸發
-(void)webViewDidClose:(WKWebView *)webView{
    NSLog(@"關閉webView");
}
#pragma mark dele<WKNavigationDelegate>      都為可選方法

// =============== 頁面加載

// 頁面開始加載時調用
-(void)webView:(WKWebView *)webView didStartProvisionalNavigation:(WKNavigation *)navigation{
    NSLog(@"頁面開始加載");
}
// 開始加載內容后調用
-(void)webView:(WKWebView *)webView didCommitNavigation:(WKNavigation *)navigation{
    NSLog(@"頁面開始加載內容");
}
// 頁面加載完成后調用
-(void)webView:(WKWebView *)webView didFinishNavigation:(WKNavigation *)navigation{
    NSLog(@"頁面加載完成");
}
// 頁面加載失敗后調用
-(void)webView:(WKWebView *)webView didFailProvisionalNavigation:(WKNavigation *)navigation withError:(NSError *)error{
    NSLog(@"頁面加載失敗");
}
// 頁面加載內容中斷時調用
-(void)webViewWebContentProcessDidTerminate:(WKWebView *)webView{
    NSLog(@"加載內容中斷");
}


// =============== 跳轉

// 是否允許跳轉(發送request請求之前調用)
-(void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler{
    /*
     navigationAction.sourceFrame   原 WKFrameInfo(只讀)
     navigationAction.targetFrame   目標 WKFrameInfo(只讀)
     navigationAction.request       request(只讀)
     navigationAction.navigationType    請求類型
        WKNavigationTypeLinkActivated,  // 鏈接href
        WKNavigationTypeFormSubmitted,  // 表單提交
        WKNavigationTypeBackForward,    // 返回
        WKNavigationTypeReload,         // 重新加載
        WKNavigationTypeFormResubmitted,// 表單重復提交
        WKNavigationTypeOther = -1,     // 其他
     
     WKNavigationActionPolicyAllow  允許
     WKNavigationActionPolicyCancel 拒絕
     */
    decisionHandler(WKNavigationActionPolicyAllow);
}
// 是否允許跳轉(發送request請求并收到響應后)
-(void)webView:(WKWebView *)webView decidePolicyForNavigationResponse:(WKNavigationResponse *)navigationResponse decisionHandler:(void (^)(WKNavigationResponsePolicy))decisionHandler{
    /*
     navigationResponse.forMainFrame    是否是main frame(只讀)
     navigationResponse.response        獲取響應response(只讀)

     
     WKNavigationResponsePolicyAllow    允許
     WKNavigationResponsePolicyCancel   拒絕
     */
    decisionHandler(WKNavigationResponsePolicyAllow);
}
// 重定向后調用(接收到服務器的跳轉請求)
-(void)webView:(WKWebView *)webView didReceiveServerRedirectForProvisionalNavigation:(WKNavigation *)navigation{
    NSLog(@"后端重定向");
}
// 跳轉失敗后調用
-(void)webView:(WKWebView *)webView didFailNavigation:(WKNavigation *)navigation withError:(NSError *)error{
    NSLog(@"跳轉失敗");
}
// https則調用
-(void)webView:(WKWebView *)webView didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition, NSURLCredential * _Nullable))completionHandler{
    /*
     NSURLSessionAuthChallengeUseCredential,                    使用(信任)證書
     NSURLSessionAuthChallengePerformDefaultHandling,           默認,忽略
     NSURLSessionAuthChallengeCancelAuthenticationChallenge,    取消
     NSURLSessionAuthChallengeRejectProtectionSpace,            這次取消,下載次還來問
     */
    // challenge.protectionSpace.authenticationMethod == NSURLAuthenticationMethodServerTrust
    completionHandler(NSURLSessionAuthChallengeUseCredential,[NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust]);
}

1.2 其他

WKWebViewConfiguration

    // 1.創建配置類
    WKWebViewConfiguration *config=[WKWebViewConfiguration new];
    // 1.1設置偏好設置
    config.preferences=({
        WKPreferences *pre=[WKPreferences new];
        [pre setMinimumFontSize:10];                            // 最小字體(默認:0)
        [pre setJavaScriptEnabled:true];                        // js是否可用(默認:true)
        [pre setJavaScriptCanOpenWindowsAutomatically:false];   // js是否能通過打開窗口 (默認:false)
        pre;
    });
    // 1.2設置內容處理池
    config.processPool=[WKProcessPool new];
    // 1.3設置交互(js調用OC)
    [config setUserContentController:({
        WKUserContentController *userC=[WKUserContentController new];
        // 添加交互,當收到js調用ssbb后 回調didReceiveScriptMessage <WKScriptMessageHandler>
        [userC addScriptMessageHandler:self name:@"ssbb"];
        
        userC;
    })];
    
    // ---------- 其他常用屬性 start 可選----------
    // 設置 持久化
    // 一個WKWebsiteDataStore對象代表了被網頁使用的各種類型的數據。包括cookies,磁盤文件,內存緩存以及持久化數據如WebSQL,IndexedDB數據庫,local storage。
    [config setWebsiteDataStore:[WKWebsiteDataStore defaultDataStore]];
    // 設置 在web全部加載到內存前是否阻止其顯示
    [config setSuppressesIncrementalRendering:true];
    // 設置 UserAgent中的應用名稱
    [config setApplicationNameForUserAgent:@""];
    // 設置 是否允許AirPlay播放媒體(默認:true)
    [config setAllowsInlineMediaPlayback:true];
    // 設置 是否忽略縮放屬性(默認:false)覆蓋網頁中的user-scalable HTML屬性
    [config setIgnoresViewportScaleLimits:true];
    // 設置 需要檢測的數據類型(可對相應的類型做處理,如鏈接則可跳轉)
    [config setDataDetectorTypes:WKDataDetectorTypeLink];
    /*
     WKDataDetectorTypeNone             不檢測(默認)
     WKDataDetectorTypePhoneNumber      電話
     WKDataDetectorTypeLink             鏈接
     WKDataDetectorTypeAddress          地址
     WKDataDetectorTypeCalendarEvent    日歷提醒事件
     WKDataDetectorTypeTrackingNumber   跟蹤號碼/查詢號/運單號
     WKDataDetectorTypeFlightNumber     航班號
     WKDataDetectorTypeLookupSuggestion
     WKDataDetectorTypeAll              檢測所有類型
     */
    // 設置 是否允許畫中畫播放?
    [config setAllowsPictureInPictureMediaPlayback:true];
    // 設置 選擇內容的粒度級別
    [config setSelectionGranularity:WKSelectionGranularityDynamic];
    /*
     WKSelectionGranularityDynamic,     用戶可自定義選擇區域(默認)
     WKSelectionGranularityCharacter,   不可自定義選擇區域
     */
    // 設置 是否使用在線的控制器(默認:false,使用本地的全屏控制器)
    [config setAllowsInlineMediaPlayback:true];
    // 設置 哪些視頻需要用戶手勢才能自動播放
    [config setMediaTypesRequiringUserActionForPlayback:WKAudiovisualMediaTypeAll];
    /*
     WKAudiovisualMediaTypeNone     所有視頻自動播放
     WKAudiovisualMediaTypeAudio    音頻
     WKAudiovisualMediaTypeVideo    視頻
     WKAudiovisualMediaTypeAll      所有都需要手勢才能播放
     */
    //
    // ---------- 其他常用屬性 end----------
2. UIWebView+原生框架(javascriptcore.framework)
  1. UIWebView 基礎使用

UIWebView : UIView <NSCoding, UIScrollViewDelegate>

    // 創建
    UIWebView *webV=[UIWebView new];
    [self.view addSubview:webV];

加載url  
    // 方式一:加載 url
    [webV loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:@""]]];
    // 方式二:加載 htmlStr
    [webV loadHTMLString:@"<p>hello</p>" baseURL:nil];
    // 方式三:加載 nsdata 
    [webView loadData:[NSData dataWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"1.docx" ofType:nil]] MIMEType:@"application/vnd.openxmlformats-officedocument.wordprocessingml.document" textEncodingName:@"UTF-8" baseURL:nil];
    /*
     1.docx
        application/vnd.openxmlformats-officedocument.wordprocessingml.document
     2.pdf
        application/pdf
     3.txt
        text/plain
     4.html
        text/html
     */


緩存
    // 注意:緩存只影響本地址,頁面內其他鏈接地址不受影響。
    NSURLRequest *request=[[NSURLRequest requestWithURL:[NSURL URLWithString:@""] cachePolicy:NSURLRequestReloadIgnoringCacheData timeoutInterval:10]];
    /*
     NSURLRequestUseProtocolCachePolicy = 0,        默認(使用緩存)
     
     NSURLRequestReloadIgnoringLocalCacheData = 1,  忽略本地緩存
     NSURLRequestReloadIgnoringLocalAndRemoteCacheData = 4, // Unimplemented
     NSURLRequestReloadIgnoringCacheData = NSURLRequestReloadIgnoringLocalCacheData,    忽略本地緩存
     
     NSURLRequestReturnCacheDataElseLoad = 2,       返回緩存,緩存沒有則請求網絡
     NSURLRequestReturnCacheDataDontLoad = 3,       返回緩存,緩存沒有則出錯
     
     NSURLRequestReloadRevalidatingCacheData = 5, // Unimplemented
     */
dele
    // dele<UIWebViewDelegate> 
    [webV setDelegate:self];

/**
  * 是否允許該request請求進行加載(加載前調用)
  *
  *  1、調用loadRequest等會調用
  *  2、調用goBack后會調用(request的緩存策略是NSURLRequestReturnCacheDataElseLoad)
  *  3、頁面內點擊其他鏈接會調用(request的緩存策略是NSURLRequestUseProtocolCachePolicy)
  *  4、重定向會調用
  */
- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType{ 

  return true;
/*
    UIWebViewNavigationTypeLinkClicked,      用戶觸擊了一個鏈接
    UIWebViewNavigationTypeFormSubmitted,    用戶提交了一個表單
    UIWebViewNavigationTypeBackForward,      用戶觸擊前進或返回按鈕
    UIWebViewNavigationTypeReload,           用戶觸擊重新加載的按鈕
    UIWebViewNavigationTypeFormResubmitted,  用戶重復提交表單
    UIWebViewNavigationTypeOther             發生其它行為
*/
}
// 開始加載(網頁內容)后調用
- (void)webViewDidStartLoad:(UIWebView *)webView{}
// (網頁內容完全顯示在控件上)加載完畢后調用
- (void)webViewDidFinishLoad:(UIWebView *)webView{

    // 獲取web頁面內容信息
    NSString *docStr=[webView stringByEvaluatingJavaScriptFromString:@"document.documentElement.textContent"];
    /*
     JavaScript的執行時間被限定在10秒鐘,如果執行時間超過10秒,那么頁面就停止執行這個腳本。
     JavaScript的執行可能阻塞主線程,所以當腳本執行的時候不允許用戶影響頁面的加載。
     JavaScript的內存分配被限制在10M,如果超出這個限制那么頁面會發生異常。
     */
}
// 加載失敗后調用
- (void)webView:(UIWebView *)webView didFailLoadWithError:(NSError *)error{}
前進后退
    // 獲取 頁面數量
    NSInteger pageCount=webV.pageCount;
    // 是否 可以回退
    BOOL isCanBack=[webV canGoBack];
    // 是否 可以前進
    BOOL isCanForward=[webV canGoForward];
    // 回退
    [webV goBack];
    // 前進
    [webV goForward];

重新加載
    // 是否 正在加載
    BOOL isLoading=[webV isLoading];
    // 重新加載(會重新調用shouldStartLoadWithRequest等)
    [webV reload];
    // 停止加載
    [webV stopLoading];


滾動條
    // 設置 是否顯示縱向滾動條
    [webV.scrollView setShowsVerticalScrollIndicator:true];
    // 設置 是否顯示橫向滾動條
    [webV.scrollView setShowsHorizontalScrollIndicator:true];

顯示
    // 是否網頁內容下載完畢才開始渲染web視圖,默認為NO
    @property (nonatomic) BOOL suppressesIncrementalRendering;
    // 是否允許長按鏈接預覽(支持3D Touch的設備),default is NO
    @property (nonatomic) BOOL allowsLinkPreview;

    // 設置是否縮放到適合屏幕大小(默認:false)
    [webV setScalesPageToFit:true];


其他
    // 設置 是否允許media后臺播放
    [webV setAllowsInlineMediaPlayback:true];
    // 獲取scrollView(只讀)
    UIScrollView *scrollView=webView.scrollView;
    // 獲取NSURLRequest (只讀)
    NSURLRequest *request=webView.request;


    // 翻頁效果(當網頁的大小超出view時,將網頁以翻頁的效果展示)
    @property (nonatomic) UIWebPaginationMode paginationMode;
    /*
     UIWebPaginationModeUnpaginated,    // 不使用翻頁效果
     UIWebPaginationModeLeftToRight,    // 將網頁超出部分分頁,從左向右進行翻頁
     UIWebPaginationModeTopToBottom,    // 將網頁超出部分分頁,從上向下進行翻頁
     UIWebPaginationModeBottomToTop,    // 將網頁超出部分分頁,從下向上進行翻頁
     UIWebPaginationModeRightToLeft     // 將網頁超出部分分頁,從右向左進行翻頁
     */
    // 分頁模式
    @property (nonatomic) UIWebPaginationBreakingMode paginationBreakingMode;
    /*
     UIWebPaginationBreakingModePage,
     UIWebPaginationBreakingModeColumn
     */
    // 每一頁的長度
    @property (nonatomic) CGFloat pageLength;
    // 每一頁的間距
    @property (nonatomic) CGFloat gapBetweenPages;
    // 是否在彈出鍵盤后允許用戶交互,默認YES
    @property (nonatomic) BOOL keyboardDisplayRequiresUserAction;

音視頻
    // 是否允許分屏播放
    @property (nonatomic) BOOL allowsPictureInPictureMediaPlayback;
    // 是否使用內嵌HTML5播放視頻(還是用本地的全屏控制)。
    // 內嵌則HTML中的video元素必須包含webkit-playsinline屬性。
    // iPhone Safari defaults to NO. iPad Safari defaults to YES
    @property (nonatomic) BOOL allowsInlineMediaPlayback;
    // 是否允許自動播放,默認為YES
    @property (nonatomic) BOOL mediaPlaybackRequiresUserAction;
    // 音頻播放是否支持air play功能,默認為YES
    @property (nonatomic) BOOL mediaPlaybackAllowsAirPlay;
  1. UIWebView 原生交互
    OC中可以直接調用JS方法
    JS可通過攔截url間接調用OC
    #import <JavaScriptCore/JavaScriptCore.h>
    <UIWebViewDelegate>


        // 創建UIWebView
        UIWebView *webV=[UIWebView new];
        [self.view addSubview:webV];
        // 布局,,,
        // 
        [webV setScalesPageToFit:true];
        // 滾動速度:正常速,默認慢速
        [webV.scrollView setDecelerationRate:UIScrollViewDecelerationRateNormal];
        // loadRequest(加載網頁)
        [webV loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:@"url"]]];

dele

        // dele
        [webV setDelegate:self];

// 加載完成后調用
-(void)webViewDidFinishLoad:(UIWebView *)webView{

》》》》》OC調js
    // 初始化一些操作  (如:提交表單,插入內容,刪除內容,修改內容,查詢內容)
    [webView stringByEvaluatingJavaScriptFromString:@"js代碼"];
    
舉例:
    // 提交表單
    [webView stringByEvaluatingJavaScriptFromString:@"document.froms[0].submit();"];
    
    // 插入內容
    [webView stringByEvaluatingJavaScriptFromString:@" js 代碼"];
    // 例:
    @"var script=document.createElement('script');"   // 可以是普通控件如img(.src .width .height)
    @"script.type='text/javascript';"
    @"script.text=\"function myFun(){"
    @"var f=document.getElementsByName(‘q’)[0];"
    @"f.value='11';"
    @"document.forms[0].submit();"
    @"}\";"
    @"document.getElementsByTagName('head')[0].appendChild(script);"
    
    // 刪除內容
    [webView stringByEvaluatingJavaScriptFromString:@"document.getElementById('a').remove()"];
    
    // 修改內容值、顯示值
    [webView stringByEvaluatingJavaScriptFromString:@"document.getElementsByName('a')[0].value='123'"];
    [webView stringByEvaluatingJavaScriptFromString:@"document.getElementsByName('a')[0].innerHTML='h123'"];
    
    // 查詢內容
    // url
    NSString *urlStr=[webView stringByEvaluatingJavaScriptFromString:@"document.location.href"];
    // title : document.title


    // 禁用 頁面元素選擇
    [webView stringByEvaluatingJavaScriptFromString:@"document.documentElement.style.webkitUserSelect='none';"];    
    // 禁用 長按彈出ActionSheet
    [webView stringByEvaluatingJavaScriptFromString:@"document.documentElement.style.webkitTouchCallout='none';"];





》》》》》 js調用OC    (方式一,原生JavaScriptCore.framework框架(iOS7))
    #import<JavaScriptCore/JavaScriptCore.h>  

    /* 2種方式:
        1、Block:暴露單個方法(不能直接使用JSValue、JSContext,造成循環引用)
        2、JSExport協議:暴露單個對象
     */

方式一(Block):
OC代碼
     #import <JavaScriptCore/JavaScriptCore.h>
    // 獲取 js代碼的執行環境
    JSContext *context = [webView valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"];
    // Block (注冊)
    context[@"js中的函數名"] = ^{
        NSArray *arg = [JSContext currentArguments];
    };
    context[@"js中的函數名"] = ^(NSDictionary *dic){
        NSLog(@"函數的實參值:%@", dic[@"color"]);
    };
js代碼
    function testClick(){
        var str1=document.getElementById("text1").value;
        var str2=document.getElementById("text2").value;
        函數名(str1,str2);
    }
      
方式二(<JSExport>):
    實現協議遵守<JSExport>,JS中調用時(會將方法轉為駝峰式,也可以使用宏JSExportAs(sbAdd,+(void)method:(int)a with:(int)b))此宏只對帶參有效
    JS中調用:對象.屬性 , 對象.方法   (不能在這增加成員變量)
}



// 是否允許加載網絡請求
-(BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType{

》》》》》 js調用OC    (方式二,攔截url)
    //
    NSString *urlStr=request.URL.absoluteString;
    //
    NSRange range=[urlStr rangeOfString:@"ssbb://"];
    if(range.location!=NSNotFound){
    
        NSString *method=[urlStr substringFromIndex:range.location+range.length];
        [self performSelector:NSSelectorFromString(method)];
        return false;
    }
    
    return true;
}
// 開始加載后調用
-(void)webViewDidStartLoad:(UIWebView *)webView{}
// 加載失敗后調用
-(void)webView:(UIWebView *)webView didFailLoadWithError:(NSError *)error{}

注意事項

1.JS值的包裝
        JS中的值拿到OC中是不能直接用的
        不能作為OC對象的屬性

    JSValue *value=[context evalutateScript:@"2+2"];     [value toInt32];
    /*
     OC type            JS type
     
     nil                undefined
     NSNull             null
     NSString           string
     NSNumber           number,boolean
     NSDictionary       Object object
     NSArray            Array object
     NSDate             Date Object
     NSBlock            Function Object
     id                 Wrapper object
     Class              Constructor object
     */
3. WebViewJavascriptBridge框架(第三方框架)
    原理:攔截URL

         pod 'WebViewJavascriptBridge'
         #import "WebViewJavascriptBridge.h"
        // 基于WKWebView,則不用再設置WKWebView 的navigationDelegate(navDele為bridge)
        // 基于UIWebView,則不用再設置dele(dele為bridge)
        
        // 0.開啟日志調試
        [WebViewJavascriptBridge enableLogging];
        // 1.創建WKWebView或UIWebView
        // 2.創建JavascriptBridge
        WebViewJavascriptBridge *_webViewBridge=[WebViewJavascriptBridge bridgeForWebView:webView];
        [_webViewBridge setWebViewDelegate:self];
        // 2.1配置
        // js調OC(注冊多個handleName,用于js中調用)
        [_webViewBridge registerHandler:@"getUserIdFromOC" handler:^(id data, WVJBResponseCallback responseCallback) {
            // data
            // callBack
            if(responseCallback){
                responseCallback(@{@"userId":@"ssbb"});
            }
        }];
        // OC調js
        [_webViewBridge callHandler:@"getUserName" data:@{@"name":@"ssbb"} responseCallback:^(id responseData) {
            // responseData
        }];
~~~~~~~~JS

<script>    
      /*這段代碼固定,必須要放到js中(第一次加載HTML時起作用,目的是加載一次wvjbscheme://__BRIDGE_LOADED__,注冊JS方法)*/
      function setupWebViewJavascriptBridge(callback) {
        if (window.WebViewJavascriptBridge) { return callback(WebViewJavascriptBridge); }
        if (window.WVJBCallbacks) { return window.WVJBCallbacks.push(callback); }
        window.WVJBCallbacks = [callback];
        var WVJBIframe = document.createElement('iframe');
        WVJBIframe.style.display = 'none';
        WVJBIframe.src = 'wvjbscheme://__BRIDGE_LOADED__';
        document.documentElement.appendChild(WVJBIframe);
        setTimeout(function() { document.documentElement.removeChild(WVJBIframe) }, 0)
      }
    
      /*與OC交互的所有JS方法都要放在此處注冊,才能調用通過JS調用OC或者讓OC調用這里的JS*/
      setupWebViewJavascriptBridge(function(bridge) {
       
       /*注冊OC調JS*/
      bridge.registerHandler('openWebviewBridgeArticle', function() {
         log("openWebviewBridgeArticle was called with by ObjC")
      })
      /*注冊OC調JS*/
      bridge.registerHandler('token', function(data, responseCallback) {
         log("G星爺: ", data)
         responseCallback({這里給我返回拼接后的地址})
      })

       /* 注冊js調OC */
       document.getElementById('register').onclick = function () {
          bridge.callHandler('ww', {'blogdURL': 'weidsfdl'}, function(response) {
                          log('JS got response', response)
                          })
       }
     })
</script>
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 230,563評論 6 544
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 99,694評論 3 429
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 178,672評論 0 383
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,965評論 1 318
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,690評論 6 413
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 56,019評論 1 329
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 44,013評論 3 449
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 43,188評論 0 290
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,718評論 1 336
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 41,438評論 3 360
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,667評論 1 374
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 39,149評論 5 365
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,845評論 3 351
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,252評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,590評論 1 295
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,384評論 3 400
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,635評論 2 380