UIWebView學習筆記
1. iOS 禁用webView加載網(wǎng)頁的長按出現(xiàn)'拷貝'事件
- (void)webViewDidFinishLoad:(UIWebView *)webView {
[self.webView stringByEvaluatingJavaScriptFromString:@"document.documentElement.style.webkitUserSelect='none';"];
[self.webView stringByEvaluatingJavaScriptFromString:@"document.documentElement.style.webkitTouchCallout='none';"];
}
2. iOS webView長按圖片,不出現(xiàn)'拷貝'(iOS9默認就是這種效果)
2.1 準備好JS文件
// js文件,如:acepack_details.js
function setImageClickFunction(){
var imgs = document.getElementsByTagName("img");
for (var i=0;i<imgs.length;i++){
imgs[i].style.webkitUserSelect='none';
}
}
2.2 注入JS
[self.webView stringByEvaluatingJavaScriptFromString:[NSString stringWithContentsOfURL:[[NSBundle mainBundle] URLForResource:@"acepack_details" withExtension:@"js"] encoding:NSUTF8StringEncoding error:nil]];
3. webView作為tableView的tableHeaderView
- 在webView的回調(diào)方法里,一定要重新設(shè)置tableView的tableHeaderView,否則會出現(xiàn)意想不到的問題。
-(void)webViewDidFinishLoad:(UIWebView *)webView {
// 獲取到webview的高度
CGFloat height = [[self.webView stringByEvaluatingJavaScriptFromString:@"document.body.scrollHeight"] floatValue];
self.webView.frame = CGRectMake(self.webView.frame.origin.x, self.webView.frame.origin.y, ScreenWidth, height);
// 一定要重新設(shè)置tableView的tableHeaderView,否則會出現(xiàn)意想不到的問題。
[self tableView].tableHeaderView = self.webView;
}
4. 替換webView中的img標簽的圖片
- 應(yīng)用場景
- 獲取頁面中所有圖片,圖片瀏覽器
- 非WIFI環(huán)境下,加載本地圖片
- (NSString *)replaceImageUrl:(NSString *) content {
// 匹配<img>標簽
NSString *urlPattern = @"<img[^>]+?src=[\"']?([^>'\"]+)[\"']?";
NSError *error = [NSError new];
NSString *tmp = content;
NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:urlPattern options:NSRegularExpressionCaseInsensitive error:&error ];
// match 這塊內(nèi)容非常強大
NSUInteger count =[regex numberOfMatchesInString:content options:NSRegularExpressionCaseInsensitive range:NSMakeRange(0, [content length])];// 匹配到的次數(shù)
UIImage *img = [UIImage imageNamed:@"icon_app"];
// 用網(wǎng)絡(luò)圖片替換webView上顯示的圖片
NSString *tmpStr = @"https://ss0.bdstatic.com/5aV1bjqh_Q23odCf/static/superman/img/logo/logo_white_fe6da1ec.png";
// 用本地圖片替換webView上顯示的圖片
tmpStr = [self htmlForJPGImage:img];
if(count > 0) {
NSArray* matches = [regex matchesInString:content options:NSMatchingReportCompletion range:NSMakeRange(0, [content length])];
for (NSTextCheckingResult *match in matches) {
NSInteger count = [match numberOfRanges]; // 匹配項
for(NSInteger index = 0;index < count;index++){
NSRange halfRange = [match rangeAtIndex:index];
if (index == 1) {
// 圖片的src屬性值
NSString *urlStr = [content substringWithRange:halfRange];
NSLog(@"=%@=",urlStr);
// 保存圖片URL
[self.imgSrcArrayM addObject:[content substringWithRange:halfRange]];
// 替換src屬性值
tmp = [tmp stringByReplacingOccurrencesOfString:urlStr withString: tmpStr];
}
}
}
}
return tmp;
}
// 編碼圖片
- (NSString *)htmlForJPGImage:(UIImage *)image {
NSData *imageData = UIImageJPEGRepresentation(image,1.0);
NSString *imageSource = [NSString stringWithFormat:@"data:image/jpg;base64,%@",[imageData base64Encoding]];
return imageSource;
}
5. webView注入JS代碼
[self.webView stringByEvaluatingJavaScriptFromString:[NSString stringWithContentsOfURL:[[NSBundle mainBundle] URLForResource:@"acepack_details" withExtension:@"js"] encoding:NSUTF8StringEncoding error:nil]];
6. webView執(zhí)行JS代碼
// 調(diào)用JS里的setImageClickFunction()函數(shù)
[self.webView stringByEvaluatingJavaScriptFromString:@"setImageClickFunction()"];
7. webView中的圖片點擊事件
7.1 準備好JS文件
// js文件,如:acepack_details.js
function setImageClickFunction(){
// 取出所有的img標簽
var imgs = document.getElementsByTagName("img");
for (var i=0;i<imgs.length;i++){
var src = imgs[i].src;
// 綁定事件
imgs[i].setAttribute("onClick","clickme(src)");
}
}
function clickme(imagesrc){
var url="ClickImage:"+imagesrc;
document.location = url;
}
7.2 注入JS
[self.webView stringByEvaluatingJavaScriptFromString:[NSString stringWithContentsOfURL:[[NSBundle mainBundle] URLForResource:@"acepack_details" withExtension:@"js"] encoding:NSUTF8StringEncoding error:nil]];
7.3 webView請求回調(diào)里,執(zhí)行JS
// 調(diào)用JS里的setImageClickFunction()函數(shù)
[self.webView stringByEvaluatingJavaScriptFromString:@"setImageClickFunction()"];
7.4 攔截請求,處理圖片的單擊事件
-(BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)_request navigationType:(UIWebViewNavigationType)navigationType {
NSString *requestString = [[_request URL] absoluteString];
NSString *prefix = @"clickimage:";
if ([requestString hasPrefix:prefix]) {
DDLogVerbose(@"%@", requestString);
NSUInteger index = 0;
NSRange range = [requestString rangeOfString:prefix];
if (range.location != NSNotFound) {
NSString *tmpSrc = [requestString substringFromIndex:(range.location + range.length)];
index = [self.imgSrcArrayM indexOfObject:tmpSrc];
}
// 顯示圖片瀏覽器
[self networkImageShow:index];
}
return YES;
}
8. 長按webView上的圖片,保存
8.1 注入JS
static NSString* const kTouchJavaScriptString=
@"document.ontouchstart=function(event){\
x=event.targetTouches[0].clientX;\
y=event.targetTouches[0].clientY;\
document.location=\"myweb:touch:start:\"+x+\":\"+y;};\
document.ontouchmove=function(event){\
x=event.targetTouches[0].clientX;\
y=event.targetTouches[0].clientY;\
document.location=\"myweb:touch:move:\"+x+\":\"+y;};\
document.ontouchcancel=function(event){\
document.location=\"myweb:touch:cancel\";};\
document.ontouchend=function(event){\
document.location=\"myweb:touch:end\";};";
[self.webView stringByEvaluatingJavaScriptFromString:kTouchJavaScriptString];
8.2 處理點擊UIWebView上面的圖片
#pragma mark - 處理點擊UIWebView上面的圖片
- (BOOL)handleWebViewClickImageWithUrl:(NSString *)url{
NSString *requestString = url;
NSArray *components = [requestString componentsSeparatedByString:@":"];
if ([components count] > 1 && [(NSString *)[components objectAtIndex:0]
isEqualToString:@"myweb"]) {
if([(NSString *)[components objectAtIndex:1] isEqualToString:@"touch"]) {
//NSLog(@"you are touching!");
//NSTimeInterval delaytime = Delaytime;
if ([(NSString *)[components objectAtIndex:2] isEqualToString:@"start"]) {
/*
@需延時判斷是否響應(yīng)頁面內(nèi)的js...
*/
_gesState = GESTURE_STATE_START;
NSLog(@"touch start!");
float ptX = [[components objectAtIndex:3]floatValue];
float ptY = [[components objectAtIndex:4]floatValue];
NSLog(@"touch point (%f, %f)", ptX, ptY);
NSString *js = [NSString stringWithFormat:@"document.elementFromPoint(%f, %f).tagName", ptX, ptY];
NSString *tagName = [self.webView stringByEvaluatingJavaScriptFromString:js];
_imgURL = nil;
if ([tagName isEqualToString:@"IMG"]) {
_imgURL = [NSString stringWithFormat:@"document.elementFromPoint(%f, %f).src", ptX, ptY];
}
if (_imgURL) {
_timer = [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:@selector(handleLongTouch) userInfo:nil repeats:NO];
}
}
else if ([(NSString *)[components objectAtIndex:2] isEqualToString:@"move"])
{
//**如果touch動作是滑動,則取消hanleLongTouch動作**//
_gesState = GESTURE_STATE_MOVE;
NSLog(@"you are move");
}
else if ([(NSString *)[components objectAtIndex:2]isEqualToString:@"end"]) {
[_timer invalidate];
_timer = nil;
_gesState = GESTURE_STATE_END;
NSLog(@"touch end");
}
}
return NO;
}
return YES;
}
// 處理長按事件
- (void)handleLongTouch {
NSLog(@"%@", _imgURL);
if (_imgURL && _gesState == GESTURE_STATE_START) {
UIActionSheet *sheet = [[UIActionSheet alloc] initWithTitle:nil delegate:self cancelButtonTitle:@"取消" destructiveButtonTitle:nil otherButtonTitles:@"保存圖片", nil];
sheet.cancelButtonIndex = sheet.numberOfButtons - 1;
[sheet showInView:[UIApplication sharedApplication].keyWindow];
}
}
// 彈出對話框
- (void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex {
if (actionSheet.numberOfButtons - 1 == buttonIndex) return;
NSString *title = [actionSheet buttonTitleAtIndex:buttonIndex];
if ([title isEqualToString:@"保存圖片"]) {
if (_imgURL) {
NSLog(@"imgurl = %@", _imgURL);
}
NSString *urlToSave = [self.webView stringByEvaluatingJavaScriptFromString:_imgURL];
NSLog(@"image url=%@", urlToSave);
NSData *data = [NSData dataWithContentsOfURL:[NSURL URLWithString:urlToSave]];
UIImage *image = [UIImage imageWithData:data];
UIImageWriteToSavedPhotosAlbum(image, self, @selector(image:didFinishSavingWithError:contextInfo:), nil);
}
}
// 回調(diào)
- (void)image:(UIImage *)image didFinishSavingWithError:(NSError *)error contextInfo:(void *)contextInfo {
if (error) {
NSLog(@"Error");
} else {
NSLog(@"OK");
}
}
9. webView緩存
9.1 緩存的意義
- webView一般是加載UI比較復(fù)雜絢麗、可變、iOS原生控件不容易實現(xiàn)的界面,所以網(wǎng)頁的元素一般都很復(fù)雜,對處于GPRS環(huán)境下的用戶而言,流量是個大問題,所以需要緩存!
- 當用戶處于斷網(wǎng)狀態(tài)下時,為了避免用戶進入空白頁面,應(yīng)該把上次已經(jīng)加載過的頁面呈現(xiàn)給用戶!
- webView的請求一般都是GET,POST請求一般是發(fā)大量數(shù)據(jù)給服務(wù)器處理(變動性比較大),因此一般只對GET請求進行緩存,而不對POST請求進行緩存。
9.2 為什么可以進行緩存?
- NSURLCache在每個UIWebView的的NSURLRequest請求中都會被調(diào)用。
- iOS 5之前:只支持內(nèi)存緩存;從iOS 5開始:同時支持內(nèi)存緩存和硬盤緩存。
9.3 怎么做到緩存?
- iOS設(shè)備上NSURLCache默認只能進行內(nèi)存緩存。可以通過子類化NSURLCache來實現(xiàn)自定義的版本從而實現(xiàn)在DISK上緩存內(nèi)容。
- 需要重寫
cachedResponseForRequest,這個會在請求發(fā)送前會被調(diào)用,從中我們可以判定是否針對此NSURLRequest返回本地數(shù)據(jù)。
- 如果本地沒有緩存就調(diào)用下面這條語句:
return [super cachedResponseForRequest:request];
9.4 NSURLCache常用方法
- 全局緩存對象
NSURLCache *cache = [NSURLCache sharedURLCache];
- 設(shè)置內(nèi)存緩存的最大容量(字節(jié)為單位,默認為512KB)
-(void)setMemoryCapacity:(NSUInteger)memoryCapacity;
- 設(shè)置硬盤緩存的最大容量(字節(jié)為單位,默認為10M)
-(void)setDiskCapacity:(NSUInteger)diskCapacity;
- 取得某個請求的緩存
-(NSCachedURLResponse *)cachedResponseForRequest:(NSURLRequest *)request; ```
5. 清除某個請求的緩存
``` objc
-(void)removeCachedResponseForRequest:(NSURLRequest *)request;
- 清除所有的緩存
-(void)removeAllCachedResponses;
9.5 設(shè)置NSURLRequest緩存策略
- NSURLRequestUseProtocolCachePolicy // 默認的緩存策略(取決于協(xié)議)
- NSURLRequestReloadIgnoringLocalCacheData // 忽略緩存,重新請求
- NSURLRequestReloadIgnoringLocalAndRemoteCacheData // 未實現(xiàn)
- NSURLRequestReloadIgnoringCacheData = NSURLRequestReloadIgnoringLocalCacheData // 忽略緩存,重新請求
- NSURLRequestReturnCacheDataElseLoad // 有緩存就用緩存,沒有緩存就重新請求
- NSURLRequestReturnCacheDataDontLoad // 有緩存就用緩存,沒有緩存就不發(fā)請求,當做請求出錯處理(用于離線模式)
- NSURLRequestReloadRevalidatingCacheData // 未實現(xiàn)