iOS中WebKit框架应用与解析(一)

本文涉及的产品
全局流量管理 GTM,标准版 1个月
云解析 DNS,旗舰版 1个月
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
简介: iOS中WebKit框架应用与解析

一、引言


       在iOS8之前,在应用中嵌入网页通常需要使用UIWebView这样一个类,这个类通过URL或者HTML文件来加载网页视图,功能十分有限,只能作为辅助嵌入原生应用程序中。虽然UIWebView也可以做原生与JavaScript交互的相关处理,然而也有很大的局限性,JavaScript要调用原生方法通常需要约定好协议之后通过Request来传递。WebKit框架中添加了一些原生与JavaScript交互的方法,增强了网页视图与原生的交互能力。并且WebKit框架中采用导航堆栈的模型来管理网页的跳转,开发者也可以更加容易的控制和管理网页的渲染。关于UIWebView的相关使用,在前面的博客中有详细介绍,地址如下。


UIWebView的使用详解:http://my.oschina.net/u/2340880/blog/469916


二、WebKit框架概览


       WebKit框架中涉及的类很多,框架的设计十分面向对象和模块化,开发者在使用时可以轻松的写出结构清晰的代码。在进行使用前,我们首先应该清楚整个框架的结构和开发思路,下面一张脑图中基本列出了WebKit框架中所涉及到的所有重要的类以及他们之间的相互关系:


如上图所示,WebKit框架中最核心的类应该属于WKWebView了,这个类专门用来渲染网页视图,其他类和协议都将基于它和服务于它。


WKWebView:网页的渲染与展示,通过WKWebViewConfiguration可以进行配置。


WKWebViewConfiguration:这个类专门用来配置WKWebView。


WKPreference:这个类用来进行M相关设置。


WKProcessPool:这个类用来配置进程池,与网页视图的资源共享有关。


WKUserContentController:这个类主要用来做native与JavaScript的交互管理。


WKUserScript:用于进行JavaScript注入。


WKScriptMessageHandler:这个类专门用来处理JavaScript调用native的方法。


WKNavigationDelegate:网页跳转间的导航管理协议,这个协议可以监听网页的活动。


WKNavigationAction:网页某个活动的示例化对象。


WKUIDelegate:用于交互处理JavaScript中的一些弹出框。


WKBackForwardList:堆栈管理的网页列表。


WKBackForwardListItem:每个网页节点对象。


三、使用WKWebViewConfiguration对WebView进行配置


       使用下面的代码可以创建一个WKWebView视图,创建WebView视图时,需要使用WKWebViewConfiguration来进行配置:


   WKWebView * WK;

   WKWebViewConfiguration * config = [[WKWebViewConfiguration alloc]init];

   WK = [[WKWebView alloc]initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height-40) configuration:config];

   [WK loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:@"http://www.baidu.com"]]];

WKWebViewConfiguration中可以进行配置的方法和属性如下:


   //设置进程池

   WKProcessPool * pool = [[WKProcessPool alloc]init];

   config.processPool = pool;

WKProcessPool类中没有暴露任何属性和方法,配置为同一个进程池的WebView会共享数据,例如Cookie、用户凭证等,开发者可以通过编写管理类来分配不同维度的WebView在不同进程池中。


   //进行偏好设置

   WKPreferences * preference = [[WKPreferences alloc]init];

   //最小字体大小 当将javaScriptEnabled属性设置为NO时,可以看到明显的效果

   preference.minimumFontSize = 0;

   //设置是否支持javaScript 默认是支持的

   preference.javaScriptEnabled = YES;

   //设置是否允许不经过用户交互由javaScript自动打开窗口

   preference.javaScriptCanOpenWindowsAutomatically = YES;

   config.preferences = preference;

WKPerference实例为WebView提供一个偏好设置。


   //设置内容交互控制器 用于处理JavaScript与native交互

   WKUserContentController * userController = [[WKUserContentController alloc]init];

   //设置处理代理并且注册要被js调用的方法名称

   [userController addScriptMessageHandler:self name:@"name"];

   //js注入,注入一个测试方法。

   NSString *javaScriptSource = @"function userFunc(){window.webkit.messageHandlers.name.postMessage( {\"name\":\"HS\"})}";

   WKUserScript *userScript = [[WKUserScript alloc] initWithSource:javaScriptSource injectionTime:WKUserScriptInjectionTimeAtDocumentStart forMainFrameOnly:YES];// forMainFrameOnly:NO(全局窗口),yes(只限主窗口)

   [userController addUserScript:userScript];

   config.userContentController = userController;

WKUserContentController专门用来管理native与JavaScript的交互行为,addScriptMessageHandler:name:方法来注册要被js调用的方法名称,之后再JavaScript中使用window.webkit.messageHandlers.name.postMessage()方法来像native发送消息,支持OC中字典,数组,NSNumber等原生数据类型,JavaScript代码中的name要和上面注册的相同。在native代理的回调方法中,会获取到JavaScript传递进来的消息,如下:


-(void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message{

   //这里可以获取到JavaScript传递进来的消息

}

WKScriptMessage类是JavaScript传递的对象实例,其中属性如下:


//传递的消息主体

@property (nonatomic, readonly, copy) id body;

//传递消息的WebView

@property (nullable, nonatomic, readonly, weak) WKWebView *webView;

//传递消息的WebView当前页面对象

@property (nonatomic, readonly, copy) WKFrameInfo *frameInfo;

//消息名称

@property (nonatomic, readonly, copy) NSString *name;

WKUserContentController实例的addUserScript:用于注入JavaScript代码,后面会专门介绍。


   //设置数据存储store

   config.websiteDataStore = [WKWebsiteDataStore defaultDataStore];

WebKit框架采用其本身的缓存框架,WKWebsiteDataStore类用来处理数据的存储,其中属性和方法如下:


@interface WKWebsiteDataStore : NSObject

//获取默认的存储器 此存储器为持久性的会被写入磁盘

+ (WKWebsiteDataStore *)defaultDataStore;

//获取一个临时的存储器

+ (WKWebsiteDataStore *)nonPersistentDataStore;

//存储器是否是临时的

@property (nonatomic, readonly, getter=isPersistent) BOOL persistent;

//所有可以存储的类型

+ (NSSet<NSString *> *)allWebsiteDataTypes;

@end

   //设置是否将网页内容全部加载到内存后再渲染

   config.suppressesIncrementalRendering = NO;

   //设置HTML5视频是否允许网页播放 设置为NO则会使用本地播放器

   config.allowsInlineMediaPlayback =  YES;

   //设置是否允许ariPlay播放

   config.allowsAirPlayForMediaPlayback = YES;

   //设置视频是否需要用户手动播放  设置为NO则会允许自动播放

   config.requiresUserActionForMediaPlayback = NO;

   //设置是否允许画中画技术 在特定设备上有效

   config.allowsPictureInPictureMediaPlayback = YES;

   //设置选择模式 是按字符选择 还是按模块选择

   /*

   typedef NS_ENUM(NSInteger, WKSelectionGranularity) {

       //按模块选择

       WKSelectionGranularityDynamic,

       //按字符选择

       WKSelectionGranularityCharacter,

   } NS_ENUM_AVAILABLE_IOS(8_0);

   */

   config.selectionGranularity = WKSelectionGranularityCharacter;

   //设置请求的User-Agent信息中应用程序名称 iOS9后可用

   config.applicationNameForUserAgent = @"HS";

四、WKWebView中的属性和方法解析


       下面列举了WKWebView中常用的属性和方法。


//设置导航代理

@property (nullable, nonatomic, weak) id <WKNavigationDelegate> navigationDelegate;

//设置UI代理

@property (nullable, nonatomic, weak) id <WKUIDelegate> UIDelegate;

//导航列表

@property (nonatomic, readonly, strong) WKBackForwardList *backForwardList;

//通过url加载网页视图

- (nullable WKNavigation *)loadRequest:(NSURLRequest *)request;

//通过文件加载网页视图

- (nullable WKNavigation *)loadFileURL:(NSURL *)URL allowingReadAccessToURL:(NSURL *)readAccessURL NS_AVAILABLE(10_11, 9_0);

//通过HTML字符串加载网页视图

- (nullable WKNavigation *)loadHTMLString:(NSString *)string baseURL:(nullable NSURL *)baseURL;

//通过data数据加载网页视图

- (nullable WKNavigation *)loadData:(NSData *)data MIMEType:(NSString *)MIMEType characterEncodingName:(NSString *)characterEncodingName baseURL:(NSURL *)baseURL NS_AVAILABLE(10_11, 9_0);

//渲染导航列表中的某个网页节点

- (nullable WKNavigation *)goToBackForwardListItem:(WKBackForwardListItem *)item;

//网页标题

@property (nullable, nonatomic, readonly, copy) NSString *title;

//网页的url

@property (nullable, nonatomic, readonly, copy) NSURL *URL;

//网页是否正在加载中

@property (nonatomic, readonly, getter=isLoading) BOOL loading;

//加载进度 可以监听这个属性的值配合UIProgressView来设计进度条

@property (nonatomic, readonly) double estimatedProgress;

//是否全部是安全连接

@property (nonatomic, readonly) BOOL hasOnlySecureContent;

//证书列表

@property (nonatomic, readonly, copy) NSArray *certificateChain;

//是否可以回退

@property (nonatomic, readonly) BOOL canGoBack;

//是否可以前进

@property (nonatomic, readonly) BOOL canGoForward;

//回退网页

- (nullable WKNavigation *)goBack;

//前进网页

- (nullable WKNavigation *)goForward;

//刷新网页

- (nullable WKNavigation *)reload;

//忽略缓存的刷新

- (nullable WKNavigation *)reloadFromOrigin;

//停止加载

- (void)stopLoading;

//执行JavaScript代码

- (void)evaluateJavaScript:(NSString *)javaScriptString completionHandler:(void (^ __nullable)(__nullable id, NSError * __nullable error))completionHandler;

//是否允许右滑返回手势

@property (nonatomic) BOOL allowsBackForwardNavigationGestures;

WKBackForwardList类为导航管理的网页列表类,其中属性方法意义如下:


@interface WKBackForwardList : NSObject

//当前所在的网页节点

@property (nullable, nonatomic, readonly, strong) WKBackForwardListItem *currentItem;

//前进的一个网页节点

@property (nullable, nonatomic, readonly, strong) WKBackForwardListItem *forwardItem;

//回退的一个网页节点

@property (nullable, nonatomic, readonly, strong) WKBackForwardListItem *backItem;

//获取某个index的网页节点

- (nullable WKBackForwardListItem *)itemAtIndex:(NSInteger)index;

//获取回退的节点数组

@property (nonatomic, readonly, copy) NSArray<WKBackForwardListItem *> *backList;

//获取前进的节点数组

@property (nonatomic, readonly, copy) NSArray<WKBackForwardListItem *> *forwardList;

@end

在WebKit中,网页节点被抽象成为了WKBackForwardListItem类,这个类中封装的属性如下:


@interface WKBackForwardListItem : NSObject

//当前节点的URL

@property (readonly, copy) NSURL *URL;

//当前节点的标题

@property (nullable, readonly, copy) NSString *title;

//创建此WebView的初始URL

@property (readonly, copy) NSURL *initialURL;

目录
相关文章
|
3天前
|
存储 算法 Java
解析HashSet的工作原理,揭示Set如何利用哈希算法和equals()方法确保元素唯一性,并通过示例代码展示了其“无重复”特性的具体应用
在Java中,Set接口以其独特的“无重复”特性脱颖而出。本文通过解析HashSet的工作原理,揭示Set如何利用哈希算法和equals()方法确保元素唯一性,并通过示例代码展示了其“无重复”特性的具体应用。
14 3
|
5天前
|
开发框架 供应链 监控
并行开发模型详解:类型、步骤及其应用解析
在现代研发环境中,企业需要在有限时间内推出高质量的产品,以满足客户不断变化的需求。传统的线性开发模式往往拖慢进度,导致资源浪费和延迟交付。并行开发模型通过允许多个开发阶段同时进行,极大提高了产品开发的效率和响应能力。本文将深入解析并行开发模型,涵盖其类型、步骤及如何通过辅助工具优化团队协作和管理工作流。
|
6天前
|
设计模式 PHP 开发者
PHP中的设计模式:桥接模式的解析与应用
在软件开发的浩瀚海洋中,设计模式如同灯塔一般,为开发者们指引方向。本文将深入探讨PHP中的一种重要设计模式——桥接模式。桥接模式巧妙地将抽象与实现分离,通过封装一个抽象的接口,使得实现和抽象可以独立变化。本文将阐述桥接模式的定义、结构、优缺点及其应用场景,并通过具体的PHP示例代码展示如何在实际项目中灵活运用这一设计模式。让我们一起走进桥接模式的世界,感受它的魅力所在。
|
6天前
|
架构师 关系型数据库 MySQL
MySQL最左前缀优化原则:深入解析与实战应用
【10月更文挑战第12天】在数据库架构设计与优化中,索引的使用是提升查询性能的关键手段之一。其中,MySQL的最左前缀优化原则(Leftmost Prefix Principle)是复合索引(Composite Index)应用中的核心策略。作为资深架构师,深入理解并掌握这一原则,对于平衡数据库性能与维护成本至关重要。本文将详细解读最左前缀优化原则的功能特点、业务场景、优缺点、底层原理,并通过Java示例展示其实现方式。
16 1
|
5天前
|
XML Java 数据格式
Spring IOC容器的深度解析及实战应用
【10月更文挑战第14天】在软件工程中,随着系统规模的扩大,对象间的依赖关系变得越来越复杂,这导致了系统的高耦合度,增加了开发和维护的难度。为解决这一问题,Michael Mattson在1996年提出了IOC(Inversion of Control,控制反转)理论,旨在降低对象间的耦合度,提高系统的灵活性和可维护性。Spring框架正是基于这一理论,通过IOC容器实现了对象间的依赖注入和生命周期管理。
15 0
|
5天前
|
供应链 网络协议 数据安全/隐私保护
|
6天前
|
机器学习/深度学习 存储 自然语言处理
基础与构建:GraphRAG架构解析及其在知识图谱中的应用
【10月更文挑战第11天】随着数据的不断增长和复杂化,传统的信息检索和生成方法面临着越来越多的挑战。特别是在处理结构化和半结构化数据时,如何高效地提取、理解和生成内容变得尤为重要。近年来,一种名为Graph Retrieval-Augmented Generation (GraphRAG) 的新架构被提出,它结合了图神经网络(GNNs)和预训练语言模型,以提高多模态数据的理解和生成能力。本文将深入探讨GraphRAG的基础原理、架构设计,并通过实际代码示例展示其在知识图谱中的应用。
25 0
|
JavaScript 前端开发 Android开发
iOS中WebKit框架应用与解析(二)
iOS中WebKit框架应用与解析
469 0
|
13天前
|
Java Android开发 Swift
安卓与iOS开发对比:平台选择对项目成功的影响
【10月更文挑战第4天】在移动应用开发的世界中,选择合适的平台是至关重要的。本文将深入探讨安卓和iOS两大主流平台的开发环境、用户基础、市场份额和开发成本等方面的差异,并分析这些差异如何影响项目的最终成果。通过比较这两个平台的优势与挑战,开发者可以更好地决定哪个平台更适合他们的项目需求。
51 1
|
20天前
|
设计模式 安全 Swift
探索iOS开发:打造你的第一个天气应用
【9月更文挑战第36天】在这篇文章中,我们将一起踏上iOS开发的旅程,从零开始构建一个简单的天气应用。文章将通过通俗易懂的语言,引导你理解iOS开发的基本概念,掌握Swift语言的核心语法,并逐步实现一个具有实际功能的天气应用。我们将遵循“学中做,做中学”的原则,让理论知识和实践操作紧密结合,确保学习过程既高效又有趣。无论你是编程新手还是希望拓展技能的开发者,这篇文章都将为你打开一扇通往iOS开发世界的大门。

推荐镜像

更多