WKWebView 基礎篇

WKWebView 是 iOS 8.0 以后用于替代 UIWebView 的瀏覽器組件蚁阳。和 UIWebView 相比,具有渲染性能更好鸽照、支持更多的 HTML5 特性韵吨、控制更加細致等諸多優(yōu)點。

一直沒沉下心來學習移宅,我們一起好好看看里面都有什么吧??

WKWebView

主要的

@interface WKWebView : UIView

//重要屬性
@property (nonatomic, readonly, copy) WKWebViewConfiguration *configuration;
@property (nullable, nonatomic, weak) id <WKNavigationDelegate> navigationDelegate;
@property (nullable, nonatomic, weak) id <WKUIDelegate> UIDelegate;
@property (nonatomic, readonly, strong) WKBackForwardList *backForwardList;

@property (nonatomic, readonly, nullable) SecTrustRef serverTrust;

@property (nullable, nonatomic, copy) NSString *customUserAgent;
@property (nonatomic) BOOL allowsLinkPreview;
@property (nonatomic, readonly, strong) UIScrollView *scrollView;
...

//加載方法
- (nullable WKNavigation *)loadRequest:(NSURLRequest *)request;
- (nullable WKNavigation *)loadFileURL:(NSURL *)URL allowingReadAccessToURL:(NSURL *)readAccessURL;
...

- (nullable WKNavigation *)goBack;
- (nullable WKNavigation *)goForward;

- (nullable WKNavigation *)reload;
- (nullable WKNavigation *)reloadFromOrigin;

//類方法
+ (BOOL)handlesURLScheme:(NSString *)urlScheme;

//與JS交互接口
- (void)evaluateJavaScript:(NSString *)javaScriptString completionHandler:(void (^ _Nullable)(_Nullable id, NSError * _Nullable error))completionHandler;
//iOS 14新增的API
- (void)evaluateJavaScript:(NSString *)javaScriptString inFrame:(nullable WKFrameInfo *)frame inContentWorld:(WKContentWorld *)contentWorld completionHandler:(void (^ _Nullable)(_Nullable id, NSError * _Nullable error))completionHandler;
- (void)callAsyncJavaScript:(NSString *)functionBody arguments:(nullable NSDictionary<NSString *, id> *)arguments inFrame:(nullable WKFrameInfo *)frame inContentWorld:(WKContentWorld *)contentWorld completionHandler:(void (^ _Nullable)(_Nullable id, NSError * _Nullable error))completionHandler;

@end

WKWebView 初始化

一個簡單用于展示的 WebView 可以是這樣的:

WKWebViewConfiguration *configuration = [[WKWebViewConfiguration alloc] init];
WKWebView *webView = ({
    webView = [[WKWebView alloc] initWithFrame:self.view.bounds configuration:configuration];
    webView.scrollView.bounces = NO;
    webView.backgroundColor = [UIColor whiteColor];
    webView;
});
    
[self.view addSubview:webView];
[webView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:@"http://baidu.com"]]];

這樣一個單純用于展示網(wǎng)頁归粉、沒有任何配置項的 WebView 就算完成了。相較于 UIWebView漏峰,我們看到多了一個 configuration 配置類型糠悼,那我們就來 Read the fucking source code…...

WKWebViewConfiguration

官方文檔是這樣描述這個類型的:

A WKWebViewConfiguration object is a collection of properties with which to initialize a web view.

一個用于初始化 web view 屬性的集合。

我們可以用它做什么呢浅乔?

  • 設置用于網(wǎng)站的初始cookie
  • 處理自定義的 URL schemes
  • 設置如何處理媒體內容
  • 管理網(wǎng)頁中選中的信息
  • 自定義注入網(wǎng)頁的腳本
  • 自定義內容的展示規(guī)則
  • …...

我們可以通過創(chuàng)建一個 WKWebViewConfiguration 對象來設置網(wǎng)頁的屬性倔喂,并且在 WebView 初始化的時候傳遞給它。注意的是只能在初始化的時候配置 configuration 中的屬性靖苇,后面是沒辦法動態(tài)再去修改這些配置的席噩。

我們通過這個類看看 WebKit 里面有哪些主要的內容:

WKProcessPool

/*! @abstract The process pool from which to obtain the view's web content
 process.
 @discussion When a web view is initialized, a new web content process
 will be created for it from the specified pool, or an existing process in
 that pool will be used.
*/
@property (nonatomic, strong) WKProcessPool *processPool;
@interface WKProcessPool : NSObject <NSSecureCoding>
@end

官方文檔解釋為一個可以在單個進程中運行多個 web 視圖的不可見 token?令牌贤壁?悼枢。進程池∑⒉穑可以看到 WKProcessPool 類沒有暴漏任何接口馒索,這意味著我們只能創(chuàng)建和讀取該對象莹妒,通過對象地址判斷是否在相同進程。

WKWebView 為了安全和穩(wěn)定性考慮绰上,會為每一個 WKWebView 實例分配獨立的進程(而不是直接使用APP的進程空間)旨怠,系統(tǒng)會有一個設定的進程個數(shù)上線。相同 WKProcessPool 對象的 WKWebView 共享相同的進程空間蜈块。這也是與 UIWebView 最大不同的一點:NSHTTPCookieStorage 中的 cookie 鉴腻,UIWebView 是可以自動攜帶使用的,但 WKWebView 無法獲取 Storage中 的 cookie百揭。

誒拘哨,那是不是放在同一個進程池中的 web view 就可以共享 cookie 了呢?帶著這個問題信峻,稍后我們會提到 cookie 有關的處理倦青。

WKPreferences

*/
@property (nonatomic, strong) WKPreferences *preferences;

針對 web 視圖的偏好設置,如果是針對 web 內容的設置還是使用 WKWebViewConfiguration 盹舞,感覺這個類還在完善产镐、擴充中,內容很少踢步。比較值得注意的是與 JavaScript 有關的兩個屬性癣亚。

//字體
@property (nonatomic) CGFloat minimumFontSize;
//是否允許在沒有用戶交互的情況下,JavaScript可以打開windows
@property (nonatomic) BOOL javaScriptCanOpenWindowsAutomatically;
//是否啟用javaScript获印,14.0 以后就廢棄了述雾,有對應替換的 API
@property (nonatomic) BOOL javaScriptEnabled;//ios(8.0, 14.0)
//是否提醒 如網(wǎng)絡釣魚或惡意軟件 等可疑的欺詐內容
@property (nonatomic) BOOL fraudulentWebsiteWarningEnabled;//ios(13.0)

WKUserContentController

/*! @abstract The user content controller to associate with the web view.
*/
@property (nonatomic, strong) WKUserContentController *userContentController;

這個類提供了一個 JavaScript 向 web view 發(fā)送消息的途徑,可以增刪用戶腳本兼丰。

JavaScript 與原生做交互玻孟,比較多的一個場景是需要調用原生的某些能力。在 UIWebView 中簡單的方式是攔截請求鳍征,根據(jù)特定的 scheme 或者參數(shù)來區(qū)分黍翎,那在 WKWebView 中則是通過 WKUserContentController 添加消息處理器。例如打開相機功能:

  • 添加腳本處理器
WKUserContentController *userContentController = [[WKUserContentController alloc] init];
[userContentController addScriptMessageHandler:self name:@"OpenCamera"];
WKWebViewConfiguration *configuration = [[WKWebViewConfiguration alloc] init];
configuration.userContentController = userContentController;
  • 實現(xiàn) WKScriptMessageHandler 代理的方法
#pragma mark - WKScriptMessageHandler
- (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message {    
if ([message.name caseInsensitiveCompare:@"OpenCamera"] == NSOrderedSame) {        
//Call your open camera action.    
}
}
  • JS 中調用
window.webkit.messageHandlers.OpenCamera.postMessage(/*需要傳的參數(shù)艳丛,兩端約定好*/);

我們看到接收 JavaScript 的消息是通過一個 WKScriptMessage 類型匣掸,我們再來簡單看下這個類

WKScriptMessage

A WKScriptMessage object contains information about a message sent from a webpage.

他的注釋就很簡單了:一個包含網(wǎng)頁發(fā)來的消息內容的對象。

// 消息體氮双、參數(shù)碰酝。允許的類型 NSNumber, NSString, NSDate, NSArray, NSDictionary, and NSNull.
@property (nonatomic, readonly, copy) id body;
// 發(fā)送消息的 web view。
@property (nullable, nonatomic, readonly, weak) WKWebView *webView;
// 前端中發(fā)送消息的 frame戴差。
@property (nonatomic, readonly, copy) WKFrameInfo *frameInfo;
// 用于接收前端消息的處理器的名字送爸。
@property (nonatomic, readonly, copy) NSString *name;
// The content world from which the message was sent. ?我也還沒用過不清楚是干嘛的。
@property (nonatomic, readonly) WKContentWorld *world API_AVAILABLE(macos(11.0), ios(14.0));

WKUserScript

A script that the web view injects into a webpage.

當需要將自定義腳本代碼注入 Web 頁面時碱璃,可以創(chuàng)建一個 WKUserScript 對象弄痹。使用此對象指定要注入的 JavaScript 代碼饭入,以及與注入該代碼的時間和方式相關的參數(shù)嵌器。通過前面提到的 WKUserContentController 調用 addUserScript: 完成注入。

@interface WKUserScript : NSObject <NSCopying>
//JS 代碼
@property (nonatomic, readonly, copy) NSString *source;
//JS 注入的時機
@property (nonatomic, readonly) WKUserScriptInjectionTime injectionTime;
//是否只用于主視圖
@property (nonatomic, readonly, getter=isForMainFrameOnly) BOOL forMainFrameOnly;
//初始化
- (instancetype)initWithSource:(NSString *)source injectionTime:(WKUserScriptInjectionTime)injectionTime forMainFrameOnly:(BOOL)forMainFrameOnly;
//iOS14 新增的一個方法谐丢,區(qū)分JS的“作用域”
- (instancetype)initWithSource:(NSString *)source injectionTime:(WKUserScriptInjectionTime)injectionTime forMainFrameOnly:(BOOL)forMainFrameOnly inContentWorld:(WKContentWorld *)contentWorld WK_API_AVAILABLE(macos(11.0), ios(14.0));
@end

WKContentWorld

An object that defines a scope of execution for JavaScript code, and which you use to prevent conflicts between different scripts.

WKContentWorld 是 iOS 14 的新增內容爽航,可以理解為不同的命名空間、不同的運行環(huán)境乾忱。顯而易見的讥珍,在邏輯上,原生的 JS 環(huán)境和 web JS 運行環(huán)境存在命名沖突的可能窄瘟。WKContentWorld 有兩個類屬性 defaultClientWorld 衷佃、pageWorld,分別代表原生和 web 容器的 JS 運行空間蹄葱。開發(fā)者也可以通過:

+ (WKContentWorld *)worldWithName:(NSString *)name;

工廠方法創(chuàng)建一個獨立的 JS 運行環(huán)境氏义。

WKWebsiteDataStore

這個類貌似包含了一個 web view 的所有數(shù)據(jù),我看完這個類的介紹图云,第一感覺是惯悠,哇,我可以窺探一切了竣况。然而克婶,除了 cookie,一毛錢都拿不到……不講了丹泉,有興趣自己試吧~~

(
WKWebsiteDataTypeDiskCache,
WKWebsiteDataTypeOfflineWebApplicationCache, 
WKWebsiteDataTypeMemoryCache,    
WKWebsiteDataTypeLocalStorage,    
WKWebsiteDataTypeFetchCache,    
WKWebsiteDataTypeCookies,    
WKWebsiteDataTypeSessionStorage,
WKWebsiteDataTypeIndexedDBDatabases,
WKWebsiteDataTypeWebSQLDatabases,
WKWebsiteDataTypeServiceWorkerRegistrations
)

WKHTTPCookieStore

A WKHTTPCookieStore object allows managing the HTTP cookies associated with a particular WKWebsiteDataStore.

用來管理與特定 WKWebsiteDataStore 相關聯(lián)的 HTTP cookie情萤。

API 看上去很簡單…但獲得 cookie 是異步操作,與 NSHTTPCookieStorage 的同步操作不同摹恨,處理起來可能要注意下紫岩。

- (void)getAllCookies:(void (^)(NSArray<NSHTTPCookie *> *))completionHandler;
- (void)setCookie:(NSHTTPCookie *)cookie completionHandler:(nullable void (^)(void))completionHandler;
- (void)deleteCookie:(NSHTTPCookie *)cookie completionHandler:(nullable void (^)(void))completionHandler;
- (void)addObserver:(id<WKHTTPCookieStoreObserver>)observer;
- (void)removeObserver:(id<WKHTTPCookieStoreObserver>)observer;

對應觀察者的協(xié)議方法:

在 cookie 發(fā)生變化時,可以異步通知睬塌,但經(jīng)測試是有一點延遲的泉蝌,有興趣可以測一測?

@protocol WKHTTPCookieStoreObserver <NSObject>
@optional
- (void)cookiesDidChangeInCookieStore:(WKHTTPCookieStore *)cookieStore;
@end

WKBackForwardList

訪問過的 web 頁面歷史記錄揩晴。

WKNavigation

WKNavigation 對象可以用來了解網(wǎng)頁的加載進度勋陪。通過 loadRequest、goBack 等方法加載頁面時硫兰,將返回一個 WKNavigation 對象诅愚。通過 WKNavigationDelegate 代理的以下幾個方法,可以知道頁面的加載情況。WKNavigationDelegate 稍后我們再說违孝。

WKNavigationAction

包含網(wǎng)頁導航信息刹前,需要據(jù)此顯示對應的操作界面。

WKFrameInfo

標識當前網(wǎng)頁內容信息的對象雌桑。

關于 WKWebView 的幾篇文章:

WKWebView 基礎篇
WKWebView 協(xié)議篇

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末喇喉,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子校坑,更是在濱河造成了極大的恐慌拣技,老刑警劉巖,帶你破解...
    沈念sama閱讀 207,113評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件耍目,死亡現(xiàn)場離奇詭異膏斤,居然都是意外死亡,警方通過查閱死者的電腦和手機邪驮,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,644評論 2 381
  • 文/潘曉璐 我一進店門莫辨,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人毅访,你說我怎么就攤上這事沮榜。” “怎么了俺抽?”我有些...
    開封第一講書人閱讀 153,340評論 0 344
  • 文/不壞的土叔 我叫張陵敞映,是天一觀的道長。 經(jīng)常有香客問我磷斧,道長振愿,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,449評論 1 279
  • 正文 為了忘掉前任弛饭,我火速辦了婚禮冕末,結果婚禮上,老公的妹妹穿的比我還像新娘侣颂。我一直安慰自己档桃,他們只是感情好,可當我...
    茶點故事閱讀 64,445評論 5 374
  • 文/花漫 我一把揭開白布憔晒。 她就那樣靜靜地躺著藻肄,像睡著了一般。 火紅的嫁衣襯著肌膚如雪拒担。 梳的紋絲不亂的頭發(fā)上嘹屯,一...
    開封第一講書人閱讀 49,166評論 1 284
  • 那天,我揣著相機與錄音从撼,去河邊找鬼州弟。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的婆翔。 我是一名探鬼主播拯杠,決...
    沈念sama閱讀 38,442評論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼啃奴!你這毒婦竟也來了潭陪?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 37,105評論 0 261
  • 序言:老撾萬榮一對情侶失蹤纺腊,失蹤者是張志新(化名)和其女友劉穎畔咧,沒想到半個月后茎芭,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體揖膜,經(jīng)...
    沈念sama閱讀 43,601評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 36,066評論 2 325
  • 正文 我和宋清朗相戀三年梅桩,在試婚紗的時候發(fā)現(xiàn)自己被綠了壹粟。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,161評論 1 334
  • 序言:一個原本活蹦亂跳的男人離奇死亡宿百,死狀恐怖趁仙,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情垦页,我是刑警寧澤雀费,帶...
    沈念sama閱讀 33,792評論 4 323
  • 正文 年R本政府宣布,位于F島的核電站痊焊,受9級特大地震影響盏袄,放射性物質發(fā)生泄漏。R本人自食惡果不足惜薄啥,卻給世界環(huán)境...
    茶點故事閱讀 39,351評論 3 307
  • 文/蒙蒙 一辕羽、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧垄惧,春花似錦刁愿、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,352評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽镜粤。三九已至,卻和暖如春脑题,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背掰曾。 一陣腳步聲響...
    開封第一講書人閱讀 31,584評論 1 261
  • 我被黑心中介騙來泰國打工旭蠕, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 45,618評論 2 355
  • 正文 我出身青樓掏熬,卻偏偏與公主長得像佑稠,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子旗芬,可洞房花燭夜當晚...
    茶點故事閱讀 42,916評論 2 344

推薦閱讀更多精彩內容

  • 前言 關于UIWebView的介紹舌胶,相信看過上文的小伙伴們,已經(jīng)大概清楚了吧疮丛,如果有問題幔嫂,歡迎提問。 本文是本系列...
    CoderLF閱讀 8,945評論 2 12
  • 版本記錄 前言 iOS8和OS X 10.10以后誊薄,蘋果推出了新框架WebKit履恩,提供了替換UIWebView的組...
    刀客傳奇閱讀 860評論 0 1
  • WKWebView是在Apple的WWDC 2014隨iOS 8和OS X 10.10出來的,是為了解決UIWeb...
    zhYx_閱讀 22,634評論 4 19
  • KVO 實現(xiàn)原理呢蔫? 利用 Runtime 動態(tài)生成一個子類切心,并且讓 instance 對象的 isa 指向這個全新...
    Junetaurus閱讀 801評論 0 13
  • 原文鏈接:https://cloud.tencent.com/developer/article/1033743[...
    Imkata閱讀 2,565評論 0 3