Initial commit
This commit is contained in:
@@ -0,0 +1,91 @@
|
||||
//
|
||||
// UMComWebView.h
|
||||
// UMCommunity
|
||||
//
|
||||
// Created by 张军华 on 16/3/21.
|
||||
// Copyright © 2016年 Umeng. All rights reserved.
|
||||
//
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
/**
|
||||
* webview的errorCode
|
||||
*/
|
||||
typedef NS_ENUM(NSInteger, UMComWebViewError) {
|
||||
UMComWebViewError_NullUrl, //!< 空的数据
|
||||
UMComWebViewError_SomeUrl, //!< 相同的url地址
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* webview的执行状态
|
||||
*/
|
||||
typedef NS_OPTIONS(NSUInteger, EUMComWebViewState) {
|
||||
EUMComWebViewStateNone = 0, //!< 初始化状态
|
||||
EUMComWebViewStateLoading = 1 << 0, //!< 加载状态
|
||||
// EUMComWebViewStateLoadingFirst = 1 << 1, //!< 初始化状态第一次loading
|
||||
// EUMComWebViewStateLoadingSendcond = 1 << 2, //!< 初始化状态第二次loading
|
||||
EUMComWebViewStateLoadingFinish = 1 << 3, //!< 加载完成
|
||||
EUMComWebViewStateLoadingError = 1 << 4, //!< 失败
|
||||
EUMComWebViewStateReload = 1 << 5, //!< 重新加载
|
||||
};
|
||||
|
||||
|
||||
extern NSString *const UMComWebViewErrorDomain;
|
||||
|
||||
|
||||
@protocol UMComWebViewDelegate <NSObject>
|
||||
|
||||
@optional
|
||||
- (BOOL)UMComWebView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType;
|
||||
- (void)UMComWebViewDidStartLoad:(UIWebView *)webView;
|
||||
- (void)UMComWebViewDidFinishLoad:(UIWebView *)webView;
|
||||
- (void)UMComWebView:(UIWebView *)webView didFailLoadWithError:(nullable NSError *)error;
|
||||
@end
|
||||
/**
|
||||
* UIWebView的子类
|
||||
* @discuss 本类只显示本地的html的数据
|
||||
*/
|
||||
@interface UMComWebView : UIWebView
|
||||
|
||||
|
||||
|
||||
@property (nullable, nonatomic, weak) id <UMComWebViewDelegate> UMComWebViewDelegate;
|
||||
|
||||
/**
|
||||
* uiview的内容高度
|
||||
*/
|
||||
@property(nonatomic,assign)CGFloat fullHeight;
|
||||
|
||||
/**
|
||||
* 当前的webview的状态
|
||||
*/
|
||||
@property(nonatomic,assign,readonly)EUMComWebViewState webviewState;
|
||||
|
||||
/**
|
||||
* 显示本地的数据
|
||||
*/
|
||||
@property(nonatomic,readonly,copy)NSString* localHtmlData;
|
||||
|
||||
/**
|
||||
* 显示远程的Url
|
||||
*/
|
||||
@property(nonatomic,readonly,copy)NSString* remoteUrl;
|
||||
|
||||
- (void)loadHTMLString:(NSString *)string baseURL:(nullable NSURL *)baseURL error:(NSError**)err;
|
||||
|
||||
|
||||
/**
|
||||
* 加载远程数据
|
||||
*
|
||||
*/
|
||||
- (void)loadRequest:(NSURLRequest*)request error:(NSError**)err;
|
||||
|
||||
|
||||
/**
|
||||
* 如果需要强行要加载已经存在的url的话,可以在调用加载函数
|
||||
* loadHTMLString or loadRequest函数之前调用此函数,强行加载
|
||||
* @discuss 此函数不推荐反复使用浪费webview的加载效率
|
||||
*/
|
||||
-(void) setReloadWebViewState;
|
||||
@end
|
||||
+287
@@ -0,0 +1,287 @@
|
||||
//
|
||||
// UMComWebView.m
|
||||
// UMCommunity
|
||||
//
|
||||
// Created by 张军华 on 16/3/21.
|
||||
// Copyright © 2016年 Umeng. All rights reserved.
|
||||
//
|
||||
|
||||
#import "UMComWebView.h"
|
||||
|
||||
NSString *const UMComWebViewErrorDomain = @"UMComWebViewErrorDomain";
|
||||
|
||||
@interface UMComWebView ()<UIWebViewDelegate>
|
||||
@property(nonatomic,readwrite,copy,)NSString* localHtmlData;
|
||||
@property(nonatomic,readwrite,copy)NSString* remoteUrl;
|
||||
|
||||
@property(nonatomic,readwrite,assign)BOOL isLoadingFinished;//控制实际加载的完成的状态
|
||||
|
||||
@property(nonatomic,readwrite,assign)EUMComWebViewState webviewState;
|
||||
@end
|
||||
|
||||
@implementation UMComWebView
|
||||
|
||||
- (instancetype)initWithFrame:(CGRect)frame
|
||||
{
|
||||
if (self = [super initWithFrame:frame]) {
|
||||
|
||||
//设置自身的回调
|
||||
self.delegate = self;
|
||||
|
||||
self.webviewState = EUMComWebViewStateNone;
|
||||
|
||||
//设置背景透明
|
||||
self.backgroundColor = [UIColor clearColor];
|
||||
self.opaque = NO;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
-(void)dealloc
|
||||
{
|
||||
NSLog(@"UMComWebView delloc");
|
||||
}
|
||||
|
||||
|
||||
- (void)loadHTMLString:(NSString *)string baseURL:(nullable NSURL *)baseURL error:(NSError**)err
|
||||
{
|
||||
//1.判断合法性
|
||||
if (!string) {
|
||||
*err = [NSError errorWithDomain:UMComWebViewErrorDomain code:UMComWebViewError_NullUrl userInfo:nil];
|
||||
self.webviewState = EUMComWebViewStateLoadingError;
|
||||
return;
|
||||
}
|
||||
|
||||
//2.检查有效性(此处忽略)
|
||||
|
||||
//如果设置为EUMComWebViewStateReload模式或者EUMComWebViewStateLoadingError,不做检查
|
||||
if (self.webviewState == EUMComWebViewStateReload || self.webviewState == EUMComWebViewStateLoadingError) {
|
||||
goto UMComWebView_loadHTMLString_condition4;
|
||||
}
|
||||
|
||||
//3.检查和上一次是否一致
|
||||
if ([self.localHtmlData isEqualToString:string]) {
|
||||
*err = [NSError errorWithDomain:UMComWebViewErrorDomain code:UMComWebViewError_SomeUrl userInfo:nil];
|
||||
return;
|
||||
}
|
||||
|
||||
UMComWebView_loadHTMLString_condition4:
|
||||
|
||||
//4.如果在加载就停止
|
||||
if (self.loading) {
|
||||
[self stopLoading];
|
||||
}
|
||||
|
||||
//5.设置本地加载的html
|
||||
self.localHtmlData = string;
|
||||
|
||||
//6.首先隐藏
|
||||
self.hidden = YES;
|
||||
|
||||
//7.设置状态
|
||||
self.webviewState = EUMComWebViewStateLoading;
|
||||
|
||||
//8.设置为true是为了只加载一次
|
||||
self.isLoadingFinished = YES;
|
||||
|
||||
//9.加载数据
|
||||
[self loadHTMLString:string baseURL:baseURL];
|
||||
}
|
||||
|
||||
|
||||
- (void)loadRequest:(NSURLRequest *)request error:(NSError**)err
|
||||
{
|
||||
//1.判断合法性
|
||||
if (!request) {
|
||||
*err = [NSError errorWithDomain:UMComWebViewErrorDomain code:UMComWebViewError_NullUrl userInfo:nil];
|
||||
self.webviewState = EUMComWebViewStateLoadingError;
|
||||
return;
|
||||
}
|
||||
|
||||
//2.检查有效性(此处忽略)
|
||||
|
||||
//3.检查request的合法性
|
||||
NSString* reuqestUrl = [request.URL absoluteString];
|
||||
if (!reuqestUrl) {
|
||||
*err = [NSError errorWithDomain:UMComWebViewErrorDomain code:UMComWebViewError_NullUrl userInfo:nil];
|
||||
self.webviewState = EUMComWebViewStateLoadingError;
|
||||
return;
|
||||
}
|
||||
|
||||
//如果设置为EUMComWebViewStateReload模式或者EUMComWebViewStateLoadingError,不做检查
|
||||
if (self.webviewState == EUMComWebViewStateReload || self.webviewState == EUMComWebViewStateLoadingError) {
|
||||
goto UMComWebView_loadRequest_condition5;
|
||||
}
|
||||
|
||||
//4.检查和上一次是否一致
|
||||
if ([self.remoteUrl isEqualToString:reuqestUrl]) {
|
||||
*err = [NSError errorWithDomain:UMComWebViewErrorDomain code:UMComWebViewError_SomeUrl userInfo:nil];
|
||||
return;
|
||||
}
|
||||
|
||||
UMComWebView_loadRequest_condition5:
|
||||
//5.如果在加载就停止
|
||||
if (self.loading) {
|
||||
[self stopLoading];
|
||||
}
|
||||
|
||||
//6.设置远程加载的url
|
||||
self.remoteUrl = reuqestUrl;
|
||||
|
||||
//7.首先隐藏
|
||||
self.hidden = YES;
|
||||
|
||||
//8.设置状态
|
||||
self.webviewState = EUMComWebViewStateLoading;
|
||||
|
||||
//9.设置为true是为了只加载一次
|
||||
self.isLoadingFinished = YES;
|
||||
|
||||
//10.执行加载
|
||||
[self loadRequest:request];
|
||||
}
|
||||
|
||||
#pragma mark - privateMethod
|
||||
|
||||
-(void) setReloadWebViewState
|
||||
{
|
||||
self.webviewState = EUMComWebViewStateReload;
|
||||
}
|
||||
|
||||
//获取宽度已经适配于webView的html。这里的原始html也可以通过js从webView里获取
|
||||
- (NSString *)htmlAdjustWithPageWidth:(CGFloat )pageWidth
|
||||
html:(NSString *)html
|
||||
webView:(UIWebView *)webView
|
||||
{
|
||||
NSMutableString *str = [NSMutableString stringWithString:html];
|
||||
//计算要缩放的比例
|
||||
CGFloat initialScale = webView.frame.size.width/pageWidth;
|
||||
//将</head>替换为meta+head
|
||||
NSString *stringForReplace = [NSString stringWithFormat:@"<meta name=\"viewport\" content=\" initial-scale=%f, minimum-scale=0.1, maximum-scale=2.0, user-scalable=yes\"></head>",initialScale];
|
||||
|
||||
NSRange range = NSMakeRange(0, str.length);
|
||||
//替换
|
||||
[str replaceOccurrencesOfString:@"</head>" withString:stringForReplace options:NSLiteralSearch range:range];
|
||||
return str;
|
||||
}
|
||||
|
||||
//处理整个屏幕的缩放比例和图片的缩放比例
|
||||
-(NSString*) processSencondLoadHTMLStringAutoFitWebViewWithd
|
||||
{
|
||||
//js获取body宽度
|
||||
NSString *bodyWidth= [self stringByEvaluatingJavaScriptFromString: @"document.body.scrollWidth "];
|
||||
|
||||
[self stringByEvaluatingJavaScriptFromString:
|
||||
@"var script = document.createElement('script');"
|
||||
"script.type = 'text/javascript';"
|
||||
"script.text = \"function ResizeImages() { "
|
||||
"var myimg,oldwidth;"
|
||||
"var maxwidth=380;" //缩放系数
|
||||
"for(i=0;i <document.images.length;i++){"
|
||||
"myimg = document.images[i];"
|
||||
"if(myimg.width > maxwidth){"
|
||||
"oldwidth = myimg.width;"
|
||||
"myimg.width = maxwidth;"
|
||||
"myimg.height = myimg.height * (maxwidth/oldwidth);"
|
||||
"}"
|
||||
"}"
|
||||
"}\";"
|
||||
"document.getElementsByTagName('head')[0].appendChild(script);"];
|
||||
|
||||
[self stringByEvaluatingJavaScriptFromString:@"ResizeImages();"];
|
||||
|
||||
int widthOfBody = [bodyWidth intValue];
|
||||
|
||||
//获取实际要显示的html
|
||||
NSString *html = [self htmlAdjustWithPageWidth:widthOfBody
|
||||
html:self.localHtmlData
|
||||
webView:self];
|
||||
return html;
|
||||
}
|
||||
|
||||
//处理图片的最大宽度的js
|
||||
-(void)processIMGAutoFitInWebView
|
||||
{
|
||||
NSString *js = @"function imgAutoFit() { \
|
||||
var imgs = document.getElementsByTagName('img'); \
|
||||
for (var i = 0; i < imgs.length; ++i) {\
|
||||
var img = imgs[i]; \
|
||||
img.style.maxWidth = %f; \
|
||||
} \
|
||||
}";
|
||||
js = [NSString stringWithFormat:js, self.bounds.size.width - 20];
|
||||
|
||||
[self stringByEvaluatingJavaScriptFromString:js];
|
||||
[self stringByEvaluatingJavaScriptFromString:@"imgAutoFit()"];
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 处理第二次请求
|
||||
*/
|
||||
-(void) processSencondLoadHTMLString
|
||||
{
|
||||
//设置为已经加载完成
|
||||
self.isLoadingFinished = YES;
|
||||
//加载实际要现实的html
|
||||
[self loadHTMLString:self.localHtmlData baseURL:nil];
|
||||
}
|
||||
|
||||
|
||||
#pragma mark - UIWebViewDelegate
|
||||
- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType
|
||||
{
|
||||
NSString* requesetURLString = request.URL.absoluteString;
|
||||
|
||||
//第一次加载的时候会回调
|
||||
if ([requesetURLString isEqualToString:@"about:blank"]) {
|
||||
return YES;
|
||||
}
|
||||
|
||||
if (self.UMComWebViewDelegate && [self.UMComWebViewDelegate respondsToSelector:@selector(UMComWebView:shouldStartLoadWithRequest:navigationType:)] ) {
|
||||
return [self.UMComWebViewDelegate UMComWebView:webView shouldStartLoadWithRequest:request navigationType:navigationType];
|
||||
}
|
||||
return YES;
|
||||
}
|
||||
- (void)webViewDidStartLoad:(UIWebView *)webView
|
||||
{
|
||||
if (self.UMComWebViewDelegate && [self.UMComWebViewDelegate respondsToSelector:@selector(UMComWebViewDidStartLoad:)]) {
|
||||
[self.UMComWebViewDelegate UMComWebViewDidStartLoad:webView];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)webViewDidFinishLoad:(UIWebView *)webView
|
||||
{
|
||||
//若加载完成第一次,则显示webView并return
|
||||
if(!self.isLoadingFinished)
|
||||
{
|
||||
[self processSencondLoadHTMLString];
|
||||
return;
|
||||
}
|
||||
|
||||
//处理图片的缩放问题
|
||||
//[self processIMGAutoFitInWebView];
|
||||
|
||||
//重置状态
|
||||
self.isLoadingFinished = NO;
|
||||
self.webviewState = EUMComWebViewStateLoadingFinish;
|
||||
|
||||
self.hidden = NO;
|
||||
if (self.UMComWebViewDelegate && [self.UMComWebViewDelegate respondsToSelector:@selector(UMComWebViewDidFinishLoad:)]) {
|
||||
__weak typeof(self) weakself = self;
|
||||
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
|
||||
[weakself.UMComWebViewDelegate UMComWebViewDidFinishLoad:webView];
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
- (void)webView:(UIWebView *)webView didFailLoadWithError:(NSError *)error
|
||||
{
|
||||
self.webviewState = EUMComWebViewStateLoadingError;
|
||||
self.isLoadingFinished = NO;
|
||||
if (self.UMComWebViewDelegate && [self.UMComWebViewDelegate respondsToSelector:@selector(UMComWebView:didFailLoadWithError:)]) {
|
||||
[self.UMComWebViewDelegate UMComWebView:webView didFailLoadWithError:error];
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
||||
Reference in New Issue
Block a user