版本记录
版本号 | 时间 |
---|---|
V1.0 | 2017.09.18 |
前言
iOS8
和OS X 10.10
以后,苹果推出了新框架WebKit
,提供了替换UIWebView
的组件WKWebView
。各种UIWebView
的问题没有了,速度更快了,占用内存少了。接下来几篇我们就对WebKit
框架进行全面深度的解析,还是老规矩,从简单到复杂,从面到点。
WebKit框架结构
先看一下该框架的基本信息。
下面我们就看一下WebKit
框架。
大家可以这个框架内容不是很多,比较重要的就是WKWebView以及其他几个代理。
在窗口中显示网页内容。 实现浏览器功能,如跟随用户激活的链接,管理后退列表以及管理最近访问过的页面的历史记录。
WebKit提供了一系列在窗口中显示网页内容的类,并实现了浏览器功能,例如用户点击链接后,管理后退列表以及管理最近访问的页面历史。 WebKit极大地简化了加载网页的复杂过程,也就是从HTTP服务器异步请求网页内容,其中响应可以以随机顺序递增或部分由网络错误引起。 WebKit还简化了显示可以包含各种MIME类型的内容的过程,并且每个框架元素都有自己的一组滚动条。
重要:只能从您的应用程序的主线程或主调度队列中调用WebKit函数和方法。
WKWebView基本
一个WKWebView
对象展示Web
内容的交互,比如app内部浏览。你可以使用WKWebView类将Web内容嵌入到你的app中,为了实现这个目的,首先需要创建一个WKWebView对象,把它设置为View,并发送申请加载Web内容。
在使用方法initWithFrame:configuration:
创建WKWebView对象以后,你需要加载网络Web内容。使用方法loadHTMLString:baseURL:
开始加载本地HTML文件,或者使用方法loadRequest:
开始加载Web内容;使用方法stopLoading
停止加载;使用属性loading
去判断Web视图是否正在记载中;给对象设置delegate
属性,需要遵守协议WKUIDelegate
以对web的内容进行跟踪。
允许用户根据Webpage历史向前或者向后进行查询,使用 goBack
和goForward
方法作为事件按钮,当用户不能移动查询的时候,使用canGoBack
和 canGoForward
属性让按钮disable
。
默认情况下,web视图上出现的电话号会自动的转化为电话链接,当电话链接被点击时,手机app就会弹出拨号页面。如果要关掉这个默认行为,需要设置dataDetectorTypes
属性为WKDataDetectorTypes
,它标志着不包含WKDataDetectorTypePhoneNumber
标志位。
你可以使用方法setMagnification:centeredAtPoint:
可编程的设置web内容第一次在webView上面展示的尺寸,这样,用户可以使用手势改变尺寸。
WKWebView API
下面我们就看一下WKWebView
的API。
#import <WebKit/WKFoundation.h>
#if WK_API_ENABLED
#if TARGET_OS_IPHONE
#import <UIKit/UIKit.h>
#else
#import <AppKit/AppKit.h>
#endif
NS_ASSUME_NONNULL_BEGIN
@class WKBackForwardList;
@class WKBackForwardListItem;
@class WKNavigation;
@class WKWebViewConfiguration;
@protocol WKNavigationDelegate;
@protocol WKUIDelegate;
/*!
A WKWebView object displays interactive Web content.
@helperclass @link WKWebViewConfiguration @/link
Used to configure @link WKWebView @/link instances.
*/
#if TARGET_OS_IPHONE
WK_EXTERN API_AVAILABLE(macosx(10.10), ios(8.0))
@interface WKWebView : UIView
#else
WK_EXTERN API_AVAILABLE(macosx(10.10), ios(8.0))
@interface WKWebView : NSView
#endif
/*! @abstract A copy of the configuration with which the web view was
initialized. */
@property (nonatomic, readonly, copy) WKWebViewConfiguration *configuration;
/*! @abstract The web view's navigation delegate. */
@property (nullable, nonatomic, weak) id <WKNavigationDelegate> navigationDelegate;
/*! @abstract The web view's user interface delegate. */
@property (nullable, nonatomic, weak) id <WKUIDelegate> UIDelegate;
/*! @abstract The web view's back-forward list. */
@property (nonatomic, readonly, strong) WKBackForwardList *backForwardList;
/*! @abstract Returns a web view initialized with a specified frame and
configuration.
@param frame The frame for the new web view.
@param configuration The configuration for the new web view.
@result An initialized web view, or nil if the object could not be
initialized.
@discussion This is a designated initializer. You can use
@link -initWithFrame: @/link to initialize an instance with the default
configuration. The initializer copies the specified configuration, so
mutating the configuration after invoking the initializer has no effect
on the web view.
*/
- (instancetype)initWithFrame:(CGRect)frame configuration:(WKWebViewConfiguration *)configuration NS_DESIGNATED_INITIALIZER;
- (nullable instancetype)initWithCoder:(NSCoder *)coder NS_DESIGNATED_INITIALIZER;
/*! @abstract Navigates to a requested URL.
@param request The request specifying the URL to which to navigate.
@result A new navigation for the given request.
*/
- (nullable WKNavigation *)loadRequest:(NSURLRequest *)request;
/*! @abstract Navigates to the requested file URL on the filesystem.
@param URL The file URL to which to navigate.
@param readAccessURL The URL to allow read access to.
@discussion If readAccessURL references a single file, only that file may be loaded by WebKit.
If readAccessURL references a directory, files inside that file may be loaded by WebKit.
@result A new navigation for the given file URL.
*/
- (nullable WKNavigation *)loadFileURL:(NSURL *)URL allowingReadAccessToURL:(NSURL *)readAccessURL API_AVAILABLE(macosx(10.11), ios(9.0));
/*! @abstract Sets the webpage contents and base URL.
@param string The string to use as the contents of the webpage.
@param baseURL A URL that is used to resolve relative URLs within the document.
@result A new navigation.
*/
- (nullable WKNavigation *)loadHTMLString:(NSString *)string baseURL:(nullable NSURL *)baseURL;
/*! @abstract Sets the webpage contents and base URL.
@param data The data to use as the contents of the webpage.
@param MIMEType The MIME type of the data.
@param encodingName The data's character encoding name.
@param baseURL A URL that is used to resolve relative URLs within the document.
@result A new navigation.
*/
- (nullable WKNavigation *)loadData:(NSData *)data MIMEType:(NSString *)MIMEType characterEncodingName:(NSString *)characterEncodingName baseURL:(NSURL *)baseURL API_AVAILABLE(macosx(10.11), ios(9.0));
/*! @abstract Navigates to an item from the back-forward list and sets it
as the current item.
@param item The item to which to navigate. Must be one of the items in the
web view's back-forward list.
@result A new navigation to the requested item, or nil if it is already
the current item or is not part of the web view's back-forward list.
@seealso backForwardList
*/
- (nullable WKNavigation *)goToBackForwardListItem:(WKBackForwardListItem *)item;
/*! @abstract The page title.
@discussion @link WKWebView @/link is key-value observing (KVO) compliant
for this property.
*/
@property (nullable, nonatomic, readonly, copy) NSString *title;
/*! @abstract The active URL.
@discussion This is the URL that should be reflected in the user
interface.
@link WKWebView @/link is key-value observing (KVO) compliant for this
property.
*/
@property (nullable, nonatomic, readonly, copy) NSURL *URL;
/*! @abstract A Boolean value indicating whether the view is currently
loading content.
@discussion @link WKWebView @/link is key-value observing (KVO) compliant
for this property.
*/
@property (nonatomic, readonly, getter=isLoading) BOOL loading;
/*! @abstract An estimate of what fraction of the current navigation has been completed.
@discussion This value ranges from 0.0 to 1.0 based on the total number of
bytes expected to be received, including the main document and all of its
potential subresources. After a navigation completes, the value remains at 1.0
until a new navigation starts, at which point it is reset to 0.0.
@link WKWebView @/link is key-value observing (KVO) compliant for this
property.
*/
@property (nonatomic, readonly) double estimatedProgress;
/*! @abstract A Boolean value indicating whether all resources on the page
have been loaded over securely encrypted connections.
@discussion @link WKWebView @/link is key-value observing (KVO) compliant
for this property.
*/
@property (nonatomic, readonly) BOOL hasOnlySecureContent;
/*! @abstract A SecTrustRef for the currently committed navigation.
@discussion @link WKWebView @/link is key-value observing (KVO) compliant
for this property.
*/
@property (nonatomic, readonly, nullable) SecTrustRef serverTrust API_AVAILABLE(macosx(10.12), ios(10.0));
/*! @abstract A Boolean value indicating whether there is a back item in
the back-forward list that can be navigated to.
@discussion @link WKWebView @/link is key-value observing (KVO) compliant
for this property.
@seealso backForwardList.
*/
@property (nonatomic, readonly) BOOL canGoBack;
/*! @abstract A Boolean value indicating whether there is a forward item in
the back-forward list that can be navigated to.
@discussion @link WKWebView @/link is key-value observing (KVO) compliant
for this property.
@seealso backForwardList.
*/
@property (nonatomic, readonly) BOOL canGoForward;
/*! @abstract Navigates to the back item in the back-forward list.
@result A new navigation to the requested item, or nil if there is no back
item in the back-forward list.
*/
- (nullable WKNavigation *)goBack;
/*! @abstract Navigates to the forward item in the back-forward list.
@result A new navigation to the requested item, or nil if there is no
forward item in the back-forward list.
*/
- (nullable WKNavigation *)goForward;
/*! @abstract Reloads the current page.
@result A new navigation representing the reload.
*/
- (nullable WKNavigation *)reload;
/*! @abstract Reloads the current page, performing end-to-end revalidation
using cache-validating conditionals if possible.
@result A new navigation representing the reload.
*/
- (nullable WKNavigation *)reloadFromOrigin;
/*! @abstract Stops loading all resources on the current page.
*/
- (void)stopLoading;
/* @abstract Evaluates the given JavaScript string.
@param javaScriptString The JavaScript string to evaluate.
@param completionHandler A block to invoke when script evaluation completes or fails.
@discussion The completionHandler is passed the result of the script evaluation or an error.
*/
- (void)evaluateJavaScript:(NSString *)javaScriptString completionHandler:(void (^ _Nullable)(_Nullable id, NSError * _Nullable error))completionHandler;
/*! @abstract A Boolean value indicating whether horizontal swipe gestures
will trigger back-forward list navigations.
@discussion The default value is NO.
*/
@property (nonatomic) BOOL allowsBackForwardNavigationGestures;
/*! @abstract The custom user agent string or nil if no custom user agent string has been set.
*/
@property (nullable, nonatomic, copy) NSString *customUserAgent API_AVAILABLE(macosx(10.11), ios(9.0));
/*! @abstract A Boolean value indicating whether link preview is allowed for any
links inside this WKWebView.
@discussion The default value is YES on Mac and iOS.
*/
@property (nonatomic) BOOL allowsLinkPreview API_AVAILABLE(macosx(10.11), ios(9.0));
#if TARGET_OS_IPHONE
/*! @abstract The scroll view associated with the web view.
*/
@property (nonatomic, readonly, strong) UIScrollView *scrollView;
#endif
#if !TARGET_OS_IPHONE
/* @abstract A Boolean value indicating whether magnify gestures will
change the web view's magnification.
@discussion It is possible to set the magnification property even if
allowsMagnification is set to NO.
The default value is NO.
*/
@property (nonatomic) BOOL allowsMagnification;
/* @abstract The factor by which the page content is currently scaled.
@discussion The default value is 1.0.
*/
@property (nonatomic) CGFloat magnification;
/* @abstract Scales the page content by a specified factor and centers the
result on a specified point.
* @param magnification The factor by which to scale the content.
* @param point The point (in view space) on which to center magnification.
*/
- (void)setMagnification:(CGFloat)magnification centeredAtPoint:(CGPoint)point;
#endif
@end
#if !TARGET_OS_IPHONE
@interface WKWebView (WKIBActions) <NSUserInterfaceValidations>
/*! @abstract Action method that navigates to the back item in the
back-forward list.
@param sender The object that sent this message.
*/
- (IBAction)goBack:(nullable id)sender;
/*! @abstract Action method that navigates to the forward item in the
back-forward list.
@param sender The object that sent this message.
*/
- (IBAction)goForward:(nullable id)sender;
/*! @abstract Action method that reloads the current page.
@param sender The object that sent this message.
*/
- (IBAction)reload:(nullable id)sender;
/*! @abstract Action method that reloads the current page, performing
end-to-end revalidation using cache-validating conditionals if possible.
@param sender The object that sent this message.
*/
- (IBAction)reloadFromOrigin:(nullable id)sender;
/*! @abstract Action method that stops loading all resources on the current
page.
@param sender The object that sent this message.
*/
- (IBAction)stopLoading:(nullable id)sender;
@end
#endif
@interface WKWebView (WKDeprecated)
@property (nonatomic, readonly, copy) NSArray *certificateChain API_DEPRECATED_WITH_REPLACEMENT("serverTrust", macosx(10.11, 10.12), ios(9.0, 10.0));
@end
NS_ASSUME_NONNULL_END
#endif
从上面可以看到,WKWebView
有一个本类,还有两个分类,WKIBActions
和WKDeprecated
。
1. 初始化方法
由于他继承的是UIView,所以可以有初始化方法initWithFrame:
,此外就是API中提供的初始化方法。
/*! @abstract Returns a web view initialized with a specified frame and
configuration.
@param frame The frame for the new web view.
@param configuration The configuration for the new web view.
@result An initialized web view, or nil if the object could not be
initialized.
@discussion This is a designated initializer. You can use
@link -initWithFrame: @/link to initialize an instance with the default
configuration. The initializer copies the specified configuration, so
mutating the configuration after invoking the initializer has no effect
on the web view.
*/
- (instancetype)initWithFrame:(CGRect)frame configuration:(WKWebViewConfiguration *)configuration NS_DESIGNATED_INITIALIZER;
2. 加载网页
#import "ViewController.h"
#import <WebKit/WebKit.h>
#import <WebKit/WKWebView.h>
@interface ViewController ()
@end
@implementation ViewController
- (void)viewDidLoad
{
[super viewDidLoad];
WKWebView *webView = [[WKWebView alloc] initWithFrame:self.view.bounds];
[webView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:@"https://www.baidu.com"]]];
[self.view addSubview:webView];
}
@end
下面看一下示例图。
3. 代理方法
WKNavigationDelegate
该方法用来追踪加载过程(页面开始加载、加载完成、加载失败)、决定是否执行跳转。
// 页面开始加载时调用
- (void)webView:(WKWebView *)webView didStartProvisionalNavigation:(WKNavigation *)navigation;
// 当内容开始返回时调用
- (void)webView:(WKWebView *)webView didCommitNavigation:(WKNavigation *)navigation;
// 页面加载完成之后调用
- (void)webView:(WKWebView *)webView didFinishNavigation:(WKNavigation *)navigation;
// 页面加载失败时调用
- (void)webView:(WKWebView *)webView didFailProvisionalNavigation:(WKNavigation *)navigation;
页面跳转的代理方法有三种,分为(收到跳转与决定是否跳转两种)
// 接收到服务器跳转请求之后调用
- (void)webView:(WKWebView *)webView didReceiveServerRedirectForProvisionalNavigation:(WKNavigation *)navigation;
// 在收到响应后,决定是否跳转
- (void)webView:(WKWebView *)webView decidePolicyForNavigationResponse:(WKNavigationResponse *)navigationResponse decisionHandler:(void (^)(WKNavigationResponsePolicy))decisionHandler;
// 在发送请求之前,决定是否跳转
- (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler;
WKUIDelegate
@protocol WKUIDelegate <NSObject>
@optional
/*! @abstract Creates a new web view.
@param webView The web view invoking the delegate method.
@param configuration The configuration to use when creating the new web
view.
@param navigationAction The navigation action causing the new web view to
be created.
@param windowFeatures Window features requested by the webpage.
@result A new web view or nil.
@discussion The web view returned must be created with the specified configuration. WebKit will load the request in the returned web view.
If you do not implement this method, the web view will cancel the navigation.
*/
- (nullable WKWebView *)webView:(WKWebView *)webView createWebViewWithConfiguration:(WKWebViewConfiguration *)configuration forNavigationAction:(WKNavigationAction *)navigationAction windowFeatures:(WKWindowFeatures *)windowFeatures;
/*! @abstract Notifies your app that the DOM window object's close() method completed successfully.
@param webView The web view invoking the delegate method.
@discussion Your app should remove the web view from the view hierarchy and update
the UI as needed, such as by closing the containing browser tab or window.
*/
- (void)webViewDidClose:(WKWebView *)webView API_AVAILABLE(macosx(10.11), ios(9.0));
/*! @abstract Displays a JavaScript alert panel.
@param webView The web view invoking the delegate method.
@param message The message to display.
@param frame Information about the frame whose JavaScript initiated this
call.
@param completionHandler The completion handler to call after the alert
panel has been dismissed.
@discussion For user security, your app should call attention to the fact
that a specific website controls the content in this panel. A simple forumla
for identifying the controlling website is frame.request.URL.host.
The panel should have a single OK button.
If you do not implement this method, the web view will behave as if the user selected the OK button.
*/
- (void)webView:(WKWebView *)webView runJavaScriptAlertPanelWithMessage:(NSString *)message initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(void))completionHandler;
/*! @abstract Displays a JavaScript confirm panel.
@param webView The web view invoking the delegate method.
@param message The message to display.
@param frame Information about the frame whose JavaScript initiated this call.
@param completionHandler The completion handler to call after the confirm
panel has been dismissed. Pass YES if the user chose OK, NO if the user
chose Cancel.
@discussion For user security, your app should call attention to the fact
that a specific website controls the content in this panel. A simple forumla
for identifying the controlling website is frame.request.URL.host.
The panel should have two buttons, such as OK and Cancel.
If you do not implement this method, the web view will behave as if the user selected the Cancel button.
*/
- (void)webView:(WKWebView *)webView runJavaScriptConfirmPanelWithMessage:(NSString *)message initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(BOOL result))completionHandler;
/*! @abstract Displays a JavaScript text input panel.
@param webView The web view invoking the delegate method.
@param message The message to display.
@param defaultText The initial text to display in the text entry field.
@param frame Information about the frame whose JavaScript initiated this call.
@param completionHandler The completion handler to call after the text
input panel has been dismissed. Pass the entered text if the user chose
OK, otherwise nil.
@discussion For user security, your app should call attention to the fact
that a specific website controls the content in this panel. A simple forumla
for identifying the controlling website is frame.request.URL.host.
The panel should have two buttons, such as OK and Cancel, and a field in
which to enter text.
If you do not implement this method, the web view will behave as if the user selected the Cancel button.
*/
- (void)webView:(WKWebView *)webView runJavaScriptTextInputPanelWithPrompt:(NSString *)prompt defaultText:(nullable NSString *)defaultText initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(NSString * _Nullable result))completionHandler;
#if TARGET_OS_IPHONE
/*! @abstract Allows your app to determine whether or not the given element should show a preview.
@param webView The web view invoking the delegate method.
@param elementInfo The elementInfo for the element the user has started touching.
@discussion To disable previews entirely for the given element, return NO. Returning NO will prevent
webView:previewingViewControllerForElement:defaultActions: and webView:commitPreviewingViewController:
from being invoked.
This method will only be invoked for elements that have default preview in WebKit, which is
limited to links. In the future, it could be invoked for additional elements.
*/
- (BOOL)webView:(WKWebView *)webView shouldPreviewElement:(WKPreviewElementInfo *)elementInfo API_AVAILABLE(ios(10.0));
/*! @abstract Allows your app to provide a custom view controller to show when the given element is peeked.
@param webView The web view invoking the delegate method.
@param elementInfo The elementInfo for the element the user is peeking.
@param defaultActions An array of the actions that WebKit would use as previewActionItems for this element by
default. These actions would be used if allowsLinkPreview is YES but these delegate methods have not been
implemented, or if this delegate method returns nil.
@discussion Returning a view controller will result in that view controller being displayed as a peek preview.
To use the defaultActions, your app is responsible for returning whichever of those actions it wants in your
view controller's implementation of -previewActionItems.
Returning nil will result in WebKit's default preview behavior. webView:commitPreviewingViewController: will only be invoked
if a non-nil view controller was returned.
*/
- (nullable UIViewController *)webView:(WKWebView *)webView previewingViewControllerForElement:(WKPreviewElementInfo *)elementInfo defaultActions:(NSArray<id <WKPreviewActionItem>> *)previewActions API_AVAILABLE(ios(10.0));
/*! @abstract Allows your app to pop to the view controller it created.
@param webView The web view invoking the delegate method.
@param previewingViewController The view controller that is being popped.
*/
- (void)webView:(WKWebView *)webView commitPreviewingViewController:(UIViewController *)previewingViewController API_AVAILABLE(ios(10.0));
#endif // TARGET_OS_IPHONE
#if !TARGET_OS_IPHONE
/*! @abstract Displays a file upload panel.
@param webView The web view invoking the delegate method.
@param parameters Parameters describing the file upload control.
@param frame Information about the frame whose file upload control initiated this call.
@param completionHandler The completion handler to call after open panel has been dismissed. Pass the selected URLs if the user chose OK, otherwise nil.
If you do not implement this method, the web view will behave as if the user selected the Cancel button.
*/
- (void)webView:(WKWebView *)webView runOpenPanelWithParameters:(WKOpenPanelParameters *)parameters initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(NSArray<NSURL *> * _Nullable URLs))completionHandler API_AVAILABLE(macosx(10.12));
#endif
@end
4. 加载JS
// 图片缩放的js代码
NSString *js = @"var count = document.images.length;
for (var i = 0; i < count; i++)
{var image = document.images[i];image.style.width=320;};
window.alert('找到' + count + '张图');";
// 根据JS字符串初始化WKUserScript对象 WKUserScript *script = [[WKUserScript alloc] initWithSource:js injectionTime:WKUserScriptInjectionTimeAtDocumentEnd forMainFrameOnly:YES];
// 根据生成的WKUserScript对象,初始化WKWebViewConfiguration WKWebViewConfiguration *config = [[WKWebViewConfiguration alloc] init];
[config.userContentController addUserScript:script];
_webView = [[WKWebView alloc] initWithFrame:self.view.bounds configuration:config];
[_webView loadHTMLString:@"<head></head>![](http://upload-images.jianshu.io/upload_images/3691932-35e3997ed3c00f05.jpg?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)"baseURL:nil];
[self.view addSubview:_webView];
WKWenView新特性及优点
- 在性能、稳定性、功能方面有很大提升(最直观的体现就是加载网页是占用的内存,模拟器加载百度与开源中国网站时,
WKWebView
占用23M,而UIWebView
占用85M); - 允许
JavaScript
的Nitro
库加载并使用(UIWebView
中限制); - 支持了更多的
HTML5
特性; - 高达
60fps
的滚动刷新率以及内置手势; - 将
UIWebViewDelegate
与UIWebView
重构成了14类与3个协议。
后记
未完,待续~~~