如下爲我的愚見, 若有不妥,望你們斧正!!! 本文的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
####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; }
下面我附上一份我本身寫的代碼:
#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; }
效果圖:
若有不足之處,還望你們斧正!!! 360°感謝!!!