淺談JS代碼和OC代碼的交互

如下爲我的愚見, 若有不妥,望你們斧正!!! 本文的GitHub源碼下載地址: https://github.com/DXSmile/JS-OC.gitcss

如需轉載,請註明轉載自DXSmile的 GitHub項目https://github.com/DXSmile/JS-OC.githtml

###簡述: 隨着應用開發技術的日漸更新迭代, 特別是HTML5出來以後, 如今不少的移動端應用開發也愈來愈趨向於使用HTML5的技術來設計和完成相對複雜的UI頁面設計和交互, 就像以前我又一篇文章寫的同樣, HTML5極可能就是下一個技術的焦點, 不少的語言,平臺,都將會更加兼容HTML5技術,企業也將會愈來愈多的使用HTML5, 那麼做爲一名iOS移動開發攻城獅來講, 咱們就須要不斷的學習成長,儘快弄精通HTML5和OC,和swift的交互,從而來實現更多更新的技術; 前文連接以下: 你不得不瞭解,甚至立馬學習的HTML5git

今天我就來和你們簡單的說一下HTML5中,JS代碼和OC代碼的交互, 因爲時間關係,我這裏只作簡單的描述,具體深刻的交互,須要你們後面不斷的練習;github

###JS和OC的交互方式簡單來講有兩種狀況:web

交互前提: 在OC端使用webView!!!

####1.OC調用JS - OC執行JS代碼 步驟1> 顯示頁面,其實就是加載請求 : 使用 [self.webView loadRequest:request];        而且讓控制器成爲webView的代理, 監聽網頁加載完畢 :  使用<UIWebViewDelegate>的代理方法:swift

/**
 *  網頁加載完畢
 */
- (void)webViewDidFinishLoad:(UIWebView *)webView { }
 ```
步驟2> 讓頁面調用OC中的腳本,它屬於webView的一個方法,特別提醒 : 執行JS腳本代碼僅僅只有這一種方法:

       [webView stringByEvaluatingJavaScriptFromString:@「JS代碼」];  ```緩存

舉例 一:app

/**
 *  網頁加載完畢
 */
- (void)webViewDidFinishLoad:(UIWebView *)webView
{
    NSString *js = @"document.getElementsByTagName('footer')[0].remove();";
    [webView stringByEvaluatingJavaScriptFromString:js];
}

舉例 二: 函數

- (void)webViewDidFinishLoad:(UIWebView *)webView
{
    NSString *JS代碼 = @"function login (username, pwd) {  "
                    "   return 10;"
                    "       }"
                    "   login();";
   //     在OC中調用JS的函數(執行JS代碼)
   [webView stringByEvaluatingJavaScriptFromString:@「JS代碼」];
}
 ```
####2. JS調用OC - 就是JS調用OC中的方法
步驟1> 需自定義href協議,能夠指定方法名和參數 : 而後將OC方法和參數值拼接在一個URL中
以下: 自定義href協議

  NSString *onload = @"this.onclick = function() {"        1> 打電話方法,有參數    "window.location.href = 'dx:call:&10086'"        2> 發信息方法,有參數    "window.location.href = 'dx:sendMsg:&10010'"        3> 關機方法,無參數      "window.location.href = 'dx:shutdown'"                                 "};"; [imgHtml appendFormat:@"<img onload="%@" width="%d" height="%d" src="%@"><div>",onload,width , height, img.src];  ``` 將OC方法和參數值拼接在一個URL中:學習

/*  通用url的設計
    1> 找一個固定的協議: 如  dx:
    2> 通常有2個參數   2.1> 方法名  2.2> 方法參數
*/
      window.location.href = 'dx:saveImageToAblum:&' + this.src

步驟2> 使用<UIWebViewDelegate>代理協議中的方法攔截請求 :  每次發送請求以前系統會自動調用該代理方法:

/**
    調用 : 每當webView發送一個請求以前都會先調用這個方法
參數說明:
    request : 即將發送的請求
    BOOL : Yes : 容許發送這個請求  No : 禁止發送這個請求
    navigationType : 是否在新窗口中打開
 */
- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType
{
//        a) 在這個代理方法中攔截JS請求的URL
//        b) 從URL中截取相應的方法名和參數
//        c) 調用方法,傳遞參數
 
      return YES/NO;
}
小結: 一般狀況來講, JS和OC的交互,就是上面兩種狀況, 理清思路,就能夠很好的作好交互了;接下來就是須要寫代碼了;

下面我附上一份我本身寫的代碼:

#pragma mark - 發送get請求 獲取數據
/** 發送get請求,獲取新聞的詳情 */
- (void)getUpData {
    // 測試地址: http://c.m.163.com/nc/article/{docid}/full.html  
    NSString *url = [NSString stringWithFormat:@"http://c.m.163.com/nc/article/%@/full.html", self.headline.docid];
    
    [[DXHTTPManager manager] GET:url parameters:nil success:^(NSURLSessionDataTask * _Nonnull task, NSDictionary *responseObject) {
        [responseObject writeToFile:@"/Users/xiongdexi/Desktop/Data/newsDetail.plist" atomically:YES];
       
        // 根據對應的docid賦值
        self.detailNews = [DXDetail detailWithDict:responseObject[self.headline.docid]];
        
        // 顯示到webView上
        [self showDetailForWebView];

    } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
        NSLog(@"加載出錯, %@", error);
    }];
    
}

接下來須要拼接html代碼:

#pragma mark - 拼接html,顯示數據到webView上
 /** 顯示到webView上 */
- (void)showDetailForWebView {
    // 1.初始化一個可變字符串
    NSMutableString *html = [NSMutableString string];
    // 2.拼接html代碼
    [html appendString:@"<html>"];
    // 2.1 頭部內容
    [html appendString:@"<head>"];
    
    // 引入css文件
    NSURL *path = [[NSBundle mainBundle]URLForResource:@"DXDetail.css" withExtension:nil];
    [html appendFormat:@"<link rel=\"stylesheet\" href=\"%@\">", path];

    [html appendString:@"</head>"];
    
    // 2.2 具體內容
    [html appendString:@"<body>"];
    
    // 將圖片插入插入body對應的標記中
    [html appendString:[self setupBody]];
    
    [html appendString:@"</body>"];
    
    // 2.3 尾部內容
    [html appendString:@"</html>"];
    
    // 3. 顯示網頁
    [self.webView loadHTMLString:html baseURL:nil];
    
}

/** 拼接body的內容  (也就是初始化body內容) */
- (NSString *)setupBody {
    
    NSMutableString *bodyM = [NSMutableString string];
    
    
    // 拼接標題
    [bodyM appendFormat:@"<div class=\"title\">%@</div>", self.detailNews.title];
    
    // 拼接時間
    [bodyM appendFormat:@"<div class=\"time\">%@</div>",self.detailNews.ptime];
    
    // 拼接圖片  img.ref ==  <!--IMG#0-->  <!--IMG#0--> --> <img src=img.src>
    [bodyM appendString:self.detailNews.body];
    
    for (DXDetailImg *img in self.detailNews.img) {
        NSMutableString *imgHtml = [NSMutableString string];
        
        // 定義圖片的寬高比 550*344  用下面的方法切割尺寸字符串
        NSArray *pixel = [img.pixel componentsSeparatedByString:@"*"];
        int width = [[pixel firstObject] intValue];
        int height = [[pixel lastObject] intValue];
        int maxWidth = [UIScreen mainScreen].bounds.size.width * 0.8;
        // 限制寬度
        if (width > maxWidth) {
            height = height * maxWidth / width; // 數學計算,等比例公式
            width = maxWidth;
        }
        
        // 拼接圖片
        [imgHtml appendString:@"<div class=\"img-parent\">"];
        
        // 給圖片綁定點擊事件onclick
        // 注意這裏須要先定義一個虛假的協議標記, 讓webView不執行跳轉,而是隻獲取圖片的url
        // 爲了預防圖片太大,沒有加載完成就調用了下面的保存方法,能夠添加一個限制,用onload來限制讓圖片下載完成以後再執行保存
        NSString *onload = @"this.onclick = function() {"
                            "window.location.href = 'dx://?src=' + this.src;"
                            "};";
        
        [imgHtml appendFormat:@"<img onload=\"%@\" width=\"%d\" height=\"%d\" src=\"%@\">",onload, width, height, img.src];
        
        [imgHtml appendString:@"</div>"];
        
        // 用一個字符串代替另外一個字符串   這樣就可讓標記圖片註釋的部位用一張真正的圖片來替代
        [bodyM replaceOccurrencesOfString:img.ref withString:imgHtml options:NSCaseInsensitiveSearch range:NSMakeRange(0, bodyM.length)];
    }
    return bodyM;
}

CSS代碼: DXDetail.css文件

.title {
    text-align : center;
    font-size : 25px;
    color : black;
    font-weight : 5px;
}

.time {
    text-align :center;
    font-size : 15px;
    color :gray;
    margin-top : 5px;
    margin-bottom : 10px;
}

.img-parent {
    text-align :center;
}

JS與OC代碼的交互:

#pragma mark - 用戶點擊圖片後的事件 JS與OC代碼的交互
/** 當用戶點擊圖片時,彈出提示框 並將圖片保存到相冊 */
// 這裏須要用到JS代碼和OC代碼的交互
- (void)saveImageToAlbum:(NSString *)imgSrc {
    
    // 1. 提示一個彈窗,提示用戶是否須要保存圖片
    UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"舒適提示" message:@"您是否須要將圖片保存到相冊?" preferredStyle:UIAlertControllerStyleActionSheet];
    // 1.1 添加兩個按鈕到彈窗上
    [alert addAction:[UIAlertAction actionWithTitle:@"是的" style:UIAlertActionStyleDestructive handler:^(UIAlertAction * _Nonnull action) {
        // 保存圖片到相冊
        [self saveToAlbum:imgSrc];
    }]];
    
    [alert addAction:[UIAlertAction actionWithTitle:@"取消" style:UIAlertActionStyleCancel handler:nil]];
    
    // 1.2 顯示
    [self presentViewController:alert animated:YES completion:nil];

}

/** 保存圖片到相冊的代碼封裝 */
- (void)saveToAlbum:(NSString *)imgSrc {
    // UIWebView 的緩存由 NSURLCache 來管理
    // 獲取緩存對象
    NSURLCache *cache = [NSURLCache sharedURLCache];
    // 在緩存中取得對應請求的圖片
    NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:imgSrc]];
    NSCachedURLResponse *response = [cache cachedResponseForRequest:request];
    NSData *imageData = response.data;
    
    // 保存圖片
    UIImage *image = [UIImage imageWithData:imageData];
    // 調用保存到相冊的方法 後面三個參數爲空,表示保存以後什麼都不作
    UIImageWriteToSavedPhotosAlbum(image, nil, nil, nil);

}

執行<UIWebViewDelegate>的代理方法

#pragma mark - 實現<UIWebViewDelegate>的代理方法
// 調用webView的代理方法之一: 每當webView發送一個請求以前就會先執行一次的方法
// 返回值: YES 表示容許發送請求, NO表示不容許發送請求
// 在webView的代理方法中截取圖片路徑,調用保存圖片到相冊的方法
- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType {
    // 經過url來截圖地址
    // 先將發送的請求裏面的url轉換成字符串
    NSString *url = request.URL.absoluteString;
    // 找到標記所在的方法,肯定截取範圍
    NSRange range = [url rangeOfString:@"dx://?src="];
    // 判斷得到的range是否不爲空,若是不爲空,就不容許發送請求,並截圖範圍以後的字符串,那就是圖片的url
    if (range.length > 0) {
        // 先肯定獲取範圍的長度,
        NSUInteger loc = range.location + range.length;
        // 根據這個長度,取範圍以後的字符串,就取得圖片的路徑了
        NSString *imgSrc = [url substringFromIndex:loc];
        // 根據路徑,將其保存到相冊
        [self saveImageToAlbum:imgSrc];
        
        return NO;
    }
  return YES;
}

效果圖: 效果圖:首頁

效果圖:webView頁面

上面的代碼,只是部分,並且尚未作代碼的重構,只是實現了功能, 若有須要源碼,能夠到個人GitHub首頁下載源碼,

若有不足之處,還望你們斧正!!! 360°感謝!!!

相關文章
相關標籤/搜索