许可协议 LCWebViewTool 根据 MIT 许可协议发布。有关详细信息,请参阅 LICENSE
一、说明
我的项目从 iOS7 开始支持,一直使用 UIWebView 作为网页容器。但是,为了更好的用户体验,我将 UIWebView 和 WKWebView 封装成一个网页容器 LCWebView。以下是我的方法:
二、LCWebViewDelegate(此代理所有方法均为 WKWebView 和 UIWebView 共同拥有的协议,支持 iOS7 及以上)
此协议有 5 个方法。(如果项目要求不多,可以只使用此协议的方法)
/**
* 加载一个 webview
*
* @param request 请求的 NSURL URLRequest
*
* @param navigationType 用户点击类型
*/
- (BOOL)LC_webView:(LCWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(LCWebViewNavigationType)navigationType;
/**
* 开始加载 webview
*/
- (void)LC_webViewDidStartLoad:(LCWebView *)webView;
/**
* 加载完成 webview
*/
- (void)LC_webViewDidFinishLoad:(LCWebView *)webView;
/**
* 加载失败 webview
*
* @param error 失败原因
*
*/
- (void)LC_webView:(LCWebView *)webView didFailLoadWithError:(NSError *)error;
/**
* js传递参数给Native处理.此处可以进行弹框显示.
*
* @param string js字符串
*
*/
- (void)LC_jsCallWebViewReceiveString:(NSString *)string;
三、LCWebViewWKSupplementDelegate(此代理所有方法均为 WKWebView 补充协议,不支持 UIWebView,为了更好的用户体验,在此添加补充。支持 iOS8 及以上)此协议有 10 个方法(在这种情况下不使用此协议的方法)
/**
* 收到服务器响应决定是否跳转(WKWebView代理方法)
*
* @param response 服务器返回值
*
*
* @param mainFrame 是否是主框架
*
*/
- (BOOL)LC_webView:(LCWebView *)webView decidePolicyForNavigationResponse:(NSURLResponse *)response IsForMainFrame:(BOOL)mainFrame API_AVAILABLE(macosx(10.10), ios(8.0));
/**
* 接收服务器跳转请求之后调用(WKWebView代理方法)
*
* @param navigation 导航对象
*
*/
-(void)LC_webView:(LCWebView *)webView didReceiveServerRedirectForProvisionalNavigation:(null_unspecified WKNavigation *)navigation API_AVAILABLE(macosx(10.10), ios(8.0));
/**
* 当内容开始返回时调用(WKWebView代理方法)
*
* @param navigation 导航对象
*
*/
- (void)LC_webView:(LCWebView *)webView didCommitNavigation:(null_unspecified WKNavigation *)navigation API_AVAILABLE(macosx(10.10), ios(8.0));//
/**
* 打开新窗口(WKWebView代理方法)
*
* @param configuration 新窗口的配置
*
* @param navigationAction 导航行为对象
*
* @param windowFeatures 窗口特性
*
*/
- (nullable LCWebView *)LC_webView:(LCWebView *)webView createWebViewWithConfiguration:(WKWebViewConfiguration *)configuration forNavigationAction:(WKNavigationAction *)navigationAction windowFeatures:(WKWindowFeatures *)windowFeatures API_AVAILABLE(macosx(10.10), ios(8.0));
/**
* 权限认证. 注意测试iOS8系统,自签证书的验证是否可以.(暂时不建议使用该方法)(WKWebView代理方法)
*
* @param challenge 验证
*
* @param completionHandler 证书验证block
*
*/
- (void)LC_webView:(LCWebView *)webView didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition disposition, NSURLCredential * _Nullable credential))completionHandler API_AVAILABLE(macosx(10.10), ios(8.0));
/**
* WKwebView关闭(WKWebView代理方法)
*/
- (void)LC_webViewDidClose:(LCWebView *)webView API_AVAILABLE(macosx(10.11), ios(9.0));
/**
* 进程终止(WKWebView代理方法)
*/
- (void)LC_webViewWebContentProcessDidTerminate:(LCWebView *)webView API_AVAILABLE(macosx(10.11), ios(9.0));
/**
* 是否预览(WKWebView代理方法)
*
* @param elementInfo 预览元素信息(url)
*
*/
- (BOOL)LC_webView:(LCWebView *)webView shouldPreviewElement:(WKPreviewElementInfo *)elementInfo API_AVAILABLE(macosx(10.12), ios(10.0));
/**
* 自定义预览视图(WKWebView代理方法)
*
* @param elementInfo 预览元素信息(url)
*
* @param previewActions 预览行为对象(title,identifier)
*
*/
- (nullable UIViewController *)LC_webView:(LCWebView *)webView previewingViewControllerForElement:(WKPreviewElementInfo *)elementInfo defaultActions:(NSArray<id <WKPreviewActionItem>> *)previewActions API_AVAILABLE(macosx(10.12), ios(10.0));
/**
* 提交预览视图(WKWebView代理方法)
*
* @param previewingViewController 预览视图ViewController
*
*/
- (void)LC_webView:(LCWebView *)webView commitPreviewingViewController:(UIViewController *)previewingViewController API_AVAILABLE(macosx(10.12), ios(10.0));
四、通用的属性和调用方法。(支持 iOS7 及以上)
@property (nonatomic, readonly, strong) UIScrollView *scrollView;
@property (nullable, nonatomic, readonly, copy) NSString *title;
@property (nullable, nonatomic, readonly, copy) NSURL *URL;
@property (nonatomic, readonly, getter=isLoading) BOOL loading;
@property (nonatomic, readonly) BOOL canGoBack;
@property (nonatomic, readonly) BOOL canGoForward;
@property (nullable, nonatomic, readonly, strong) NSURLRequest *request;
@property (nonatomic, weak, nullable)id<LCWebViewDelegate> webDelegate;
@property (nonatomic, weak, nullable)id<LCWebViewWKSupplementDelegate> supplementDelegate;
/**
* LCWebView 初始化方法
*
* @param configuration WKWebView自定义配置
*
*/
- (instancetype)initWithFrame:(CGRect)frame withWKWebViewConfiguration:(nullable WKWebViewConfiguration * )configuration;
/**
* LCWebView 刷新
*/
- (nullable WKNavigation *)LC_reload;
/**
* LCWebView 返回下一页
*/
- (nullable WKNavigation *)LC_goBack;
/**
* LCWebView 返回上一页
*/
- (nullable WKNavigation *)LC_goForward;
/**
* LCWebView 停止加载
*/
- (void)LC_stopLoading;
/**
* 加载一个 webview
*
* @param request 请求的 NSURL URLRequest
*/
- (nullable WKNavigation *)LC_loadRequest:(NSURLRequest*)request;
/**
* 加载一个 webview
*
* @param string 请求的 URL String
*
* @param baseURL 请求的 baseURL
*
*/
- (nullable WKNavigation *)LC_loadHTMLString:(NSString *)string baseURL:(nullable NSURL *)baseURL;
/**
* 加载本地网页
*
* @param htmlName 请求的本地 HTML 文件名
*/
- (nullable WKNavigation *)LC_loadHTMLFileName:(NSString *)htmlName;
/**
* oc调js,只提供此方法
*
* @param javaScriptString js字符串
*
* @param completionHandler block
*
*/
- (void)LC_evaluatJavaScript:(NSString *)javaScriptString completionHandler:(void (^ _Nullable)(_Nullable id, NSError *_Nullable error))completionHandler;
五、UIWebView 的属性配置(仅支持 iOS7,可以不做任何设置)
/**
* 缩放页面适应屏幕大小(仅设置UIWebView) 注:iPhone Safari defaults to NO
*/
@property (nonatomic) BOOL scalesPageToFit;
/**
* 把网页上内容转换成可点击的链接(仅设置UIWebView) 注:NS_OPTIONS 按位掩码 可以多选(电话,超链接,地址等等)
*/
@property (nonatomic) UIDataDetectorTypes dataDetectorTypes;
/**
* 使用内嵌Html播放还是使用本地控制(仅设置UIWebView) 注:iPhone Safari defaults to NO. iPad Safari defaults to YES
* 内嵌Html播放时,在HTML中的video元素必须包含webkit-playsinline属性
*/
@property (nonatomic) BOOL allowsInlineMediaPlayback;
/**
* 自动播放还是手动播放(仅设置UIWebView) 注:iPhone and iPad Safari both default to YES
*/
@property (nonatomic) BOOL mediaPlaybackRequiresUserAction;
/**
* 页面是否可以投影Air Play(仅设置UIWebView) 注:iPhone and iPad Safari both default to YES
*/
@property (nonatomic) BOOL mediaPlaybackAllowsAirPlay;
/**
* 设置是否将数据加载入内存后渲染界面(仅设置UIWebView) 注:iPhone and iPad Safari both default to NO
*/
@property (nonatomic) BOOL suppressesIncrementalRendering;
/**
* 设置用户是否能打开keyboard交互(仅设置UIWebView) 注:default is YES
*/
@property (nonatomic) BOOL keyboardDisplayRequiresUserAction;
/**
* 当网页的大小超出view时,将网页以翻页效果展示(仅设置UIWebView) 注:NS_ENUM
*/
@property (nonatomic) UIWebPaginationMode paginationMode;
/**
* 决定CSS的属性分页是否可用(仅设置UIWebView) 注:NS_ENUM 默认是UIWebPaginationBreakingModePage
*/
@property (nonatomic) UIWebPaginationBreakingMode paginationBreakingMode;
/**
* 每一页的长度(仅设置UIWebView)
*/
@property (nonatomic) CGFloat pageLength;
/**
* 每一页的间距(仅设置UIWebView)
*/
@property (nonatomic) CGFloat gapBetweenPages;
/**
* 获取页数(仅设置UIWebView)
*/
@property (nonatomic, readonly) NSUInteger pageCount;
六、WKWebView 的属性和额外方法(为了更好的用户体验,建议设置,但不设置也可以。支持 iOS8 及以上)
/**
* 网站列表,历史记录,可以通过前进和后退 (仅设置WKWebView)
*/
@property (nonatomic, readonly, strong) WKBackForwardList *backForwardList;
/**
* 网页加载进度(仅设置WKWebView) 可以使用KVO监听
*/
@property (nonatomic, assign) double estimatedProgress;
/**
* 是否安全加载页面(仅设置WKWebView)
*/
@property (nonatomic, readonly) BOOL hasOnlySecureContent;
/**
* 是否允许水平滑动前进后退(仅设置WKWebView) 注:defaults to NO
*/
@property (nonatomic) BOOL allowsBackForwardNavigationGestures;
/**
* 设置用户代理UserAgent(仅设置WKWebView) 注:iOS9及以上
*/
@property (nullable, nonatomic, copy) NSString *customUserAgent API_AVAILABLE(macosx(10.11), ios(9.0));
/**
* 是否支持链接预览,3DTouch等等(仅设置WKWebView) 注:iOS9及以上
*/
@property (nonatomic) BOOL allowsLinkPreview API_AVAILABLE(macosx(10.11), ios(9.0));
/**
* 定向跳转WKBackForwardList中某个页面
*
* @param item 历史记录表中某个网页的对象.(仅支持WKWebView)
*/
- (nullable WKNavigation *)LC_goToBackForwardListItem:(WKBackForwardListItem *)item;
/**
* 比较网络数据是否有变化,没有变化则使用缓存,否则从新请求.(仅支持WKWebView)
*/
- (nullable WKNavigation *)LC_reloadFromOrigin;
七、补充说明
(1) LCWebView 的初始化方法只提供一个方法
- (instancetype)initWithFrame:(CGRect)frame withWKWebViewConfiguration:(nullable WKWebViewConfiguration * )configuration;
当手机系统版本为 iOS7 时使用 UIWebView 来加载,当手机系统为 iOS8 及以上时,LCWebView 内部使用 WKWebView 来加载。如果参数:configuration 设置为 nil 时,LCWebView 内部会默认设置好 configuration。
(2) LCWebView 的 Native 调用 js 只提供一个方法
- (void)LC_evaluatJavaScript:(NSString *)javaScriptString completionHandler:(void (^ _Nullable)(_Nullable id, NSError *_Nullable error))completionHandler;
(3) LCWebView 调用 Native 的 js 只提供 LCWebViewDelegate 协议中的一个方法
- (void)LC_jsCallWebViewReceiveString:(NSString *)string;
注:所有的 js 调用 Native 的弹框都通过该方法来处理。例如如下前端代码,通过传递给 Native 端的字符串来进行弹框显示,具体可以看 Demo
<input type="button" value="js传参给Native" onclick="callFunc()">
<script type="text/javascript">
function callOC(func,param){
var url= "func=" + func;
for(var i in param)
{
url = url + "&" + i + "=" + param[i];
}
window.webkit.messageHandlers.Native.postMessage(url);
}
function callFunc(){
var stack = new Array();
stack["user"] = "泰日天";
stack["message"] = "我是帅哥吗?";
stack["time"] = new Date();
callOC("Alert",stack);
}
</script>
(4) LCWebView 提供加载网页进度。可以通过 KVO 来获取,详情看 Demo。
- (nullable WKNavigation *)LC_loadRequest:(NSURLRequest*)request;
(5) LCWebView 关于 HTTPS 加载自签名证书的解决方法:UIWebView 的 HTTPS 自签名证书解决方法:http://blog.csdn.net/luochuanad/article/details/53410537
WKWebView 的 HTTPS 自签名证书的解决方法:https://github.com/LuochuanAD/HybirdWKWebVIew
LCWebView 关于 cookie 的问题:https://www.jianshu.com/p/85f24794bbea
CocoaPods 是由以下团队提供的项目