显著提高iOS应用中Web页面的加载速度 - 提前下载页面的关键资源(如JavaScript、CSS和图像)

在这里插入图片描述

手动下载并缓存资源是一种有效的方式,可以确保在需要时资源已经在本地存储,这样可以显著提高加载速度。

缓存整个 web 页面的所有资源文件

具体实现步骤

  1. 下载和缓存资源:包括 HTML 文件、CSS、JavaScript 和图像。
  2. 在应用启动时预加载资源
  3. 构建包含所有预加载资源的 HTML 字符串
  4. 加载构建的 HTML 字符串到 WKWebView

资源下载和缓存管理类

import Foundationclass ResourceDownloader {static let shared = ResourceDownloader()private init() {}func downloadResources() {let resources = [URL(string: "https://www.example.com/styles.css")!,URL(string: "https://www.example.com/script.js")!,URL(string: "https://www.example.com/image.png")!,URL(string: "https://www.example.com/index.html")!]for resource in resources {downloadResource(from: resource)}}private func downloadResource(from url: URL) {let task = URLSession.shared.downloadTask(with: url) { localURL, response, error inguard let localURL = localURL else { return }do {let data = try Data(contentsOf: localURL)self.cacheResource(data: data, url: url)} catch {print("Failed to load resource: \(error)")}}task.resume()}private func cacheResource(data: Data, url: URL) {let cacheDirectory = FileManager.default.urls(for: .cachesDirectory, in: .userDomainMask).first!let fileURL = cacheDirectory.appendingPathComponent(url.lastPathComponent)do {try data.write(to: fileURL)print("Resource cached: \(fileURL)")} catch {print("Failed to cache resource: \(error)")}}func getCachedResource(for url: URL) -> Data? {let cacheDirectory = FileManager.default.urls(for: .cachesDirectory, in: .userDomainMask).first!let fileURL = cacheDirectory.appendingPathComponent(url.lastPathComponent)return try? Data(contentsOf: fileURL)}
}

在应用启动时预加载资源

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {var window: UIWindow?func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {// 预加载资源ResourceDownloader.shared.downloadResources()return true}
}

使用缓存的资源加载完整页面

import UIKit
import WebKitclass ViewController: UIViewController {var webView: WKWebView!override func viewDidLoad() {super.viewDidLoad()webView = WKWebView(frame: self.view.bounds)self.view.addSubview(webView)// 构建完整的HTML内容if let htmlURL = URL(string: "https://www.example.com/index.html"),let cachedHTML = ResourceDownloader.shared.getCachedResource(for: htmlURL),let htmlString = String(data: cachedHTML, encoding: .utf8) {let completeHTMLString = embedCachedResources(in: htmlString)// 加载HTML内容到webViewwebView.loadHTMLString(completeHTMLString, baseURL: nil)} else {// 如果没有缓存,则加载远程 URLlet request = URLRequest(url: URL(string: "https://www.example.com")!)webView.load(request)}}private func embedCachedResources(in htmlString: String) -> String {var modifiedHTMLString = htmlString// 嵌入预加载的CSSif let cssURL = URL(string: "https://www.example.com/styles.css"),let cachedCSS = ResourceDownloader.shared.getCachedResource(for: cssURL),let cssString = String(data: cachedCSS, encoding: .utf8) {let cssTag = "<style>\(cssString)</style>"modifiedHTMLString = modifiedHTMLString.replacingOccurrences(of: "<link rel=\"stylesheet\" href=\"styles.css\">", with: cssTag)}// 嵌入预加载的JavaScriptif let jsURL = URL(string: "https://www.example.com/script.js"),let cachedJS = ResourceDownloader.shared.getCachedResource(for: jsURL),let jsString = String(data: cachedJS, encoding: .utf8) {let jsTag = "<script>\(jsString)</script>"modifiedHTMLString = modifiedHTMLString.replacingOccurrences(of: "<script src=\"script.js\" defer></script>", with: jsTag)}// 嵌入预加载的图像if let imageURL = URL(string: "https://www.example.com/image.png"),let cachedImage = ResourceDownloader.shared.getCachedResource(for: imageURL) {let base64Image = cachedImage.base64EncodedString()let imgTag = "<img src='data:image/png;base64,\(base64Image)' alt='Preloaded Image'>"modifiedHTMLString = modifiedHTMLString.replacingOccurrences(of: "<img src=\"image.png\" alt=\"Preloaded Image\">", with: imgTag)}return modifiedHTMLString}
}

详细说明

  1. 资源下载和缓存

    • 使用 URLSession 下载资源(包括HTML文件、CSS、JavaScript和图像),并将其缓存到本地存储。
    • 下载完成后,资源数据被写入本地存储,以便后续使用。
  2. 预加载资源

    • 在应用启动时调用 downloadResources() 方法,预先下载和缓存所需的资源。
  3. 使用缓存的资源加载完整页面

    • viewDidLoad() 方法中,通过 getCachedResource(for:) 获取缓存的HTML内容。
    • 使用 embedCachedResources(in:) 方法,将预加载的 CSS、JavaScript 和图像嵌入到 HTML 内容中。
    • 使用 webView.loadHTMLString(completeHTMLString, baseURL: nil) 加载修改后的 HTML 内容。

通过这种方式,可以确保在加载页面时直接使用本地缓存的资源,从而显著提高页面加载速度,提供更好的用户体验。


只缓存 CSS、JavaScript 和图像

只有 CSS、JavaScript 和图像是预加载的,而 HTML 文件是在打开 WKWebView 时才开始下载的。这种策略在某些情况下可能更加高效,尤其是当 HTML 文件需要动态生成或者频繁更新时。

为什么预加载 CSS、JavaScript 和图像?

预加载 CSS、JavaScript 和图像有几个优点:

  • 减少首次渲染时间:通过提前加载关键资源,可以显著减少页面首次渲染的时间,提高用户体验。
  • 减轻服务器压力:本地缓存的资源可以减少重复请求,减轻服务器的负载。
  • 提高离线体验:在某些情况下,即使没有网络连接,用户也能看到页面的一部分内容。

什么时候 HTML 文件在打开 WKWebView 时下载?

  • 动态内容:如果 HTML 文件内容是动态生成的(例如,包含个性化数据或实时更新的数据),那么在每次加载页面时请求最新的 HTML 文件是必要的。
  • 频繁更新:如果 HTML 文件内容频繁更新,预加载 HTML 文件可能会导致内容不一致。
  • 用户特定数据:某些应用需要根据用户的身份或状态生成不同的 HTML 内容。

完整的 Swift 代码实现

展示如何预加载 CSS、JavaScript 和图像,并在打开 WKWebView 时下载 HTML 文件。

import UIKit
import WebKitclass ViewController: UIViewController {var webView: WKWebView!override func viewDidLoad() {super.viewDidLoad()// 创建并配置 WKWebViewlet configuration = WKWebViewConfiguration()let urlSchemeHandler = LocalResourceHandler()configuration.setURLSchemeHandler(urlSchemeHandler, forURLScheme: "local")webView = WKWebView(frame: self.view.bounds, configuration: configuration)self.view.addSubview(webView)// 加载远程 HTML 文件if let htmlURL = URL(string: "https://www.example.com/index.html") {let request = URLRequest(url: htmlURL)webView.load(request)}}
}class LocalResourceHandler: NSObject, WKURLSchemeHandler {func webView(_ webView: WKWebView, start urlSchemeTask: WKURLSchemeTask) {guard let url = urlSchemeTask.request.url else {return}// 仅处理特定的 URL 方案,例如 "local"guard url.scheme == "local" else {// 对于非 "local" 方案的请求,不处理return}if let data = ResourceDownloader.shared.getCachedResource(for: url) {let mimeType = determineMimeType(for: url)let response = URLResponse(url: url, mimeType: mimeType, expectedContentLength: data.count, textEncodingName: nil)urlSchemeTask.didReceive(response)urlSchemeTask.didReceive(data)urlSchemeTask.didFinish()} else {// 缓存资源不可用,发起网络请求downloadResource(from: url, urlSchemeTask: urlSchemeTask)}}func webView(_ webView: WKWebView, stop urlSchemeTask: WKURLSchemeTask) {}private func determineMimeType(for url: URL) -> String {switch url.pathExtension {case "css":return "text/css"case "js":return "application/javascript"case "png":return "image/png"default:return "text/plain"}}private func downloadResource(from url: URL, urlSchemeTask: WKURLSchemeTask) {let task = URLSession.shared.dataTask(with: url) { data, response, error inif let error = error {urlSchemeTask.didFailWithError(error)return}guard let data = data, let response = response else {urlSchemeTask.didFailWithError(NSError(domain: "LocalResourceHandler", code: 404, userInfo: nil))return}// 缓存资源ResourceDownloader.shared.cacheResource(data: data, url: url)// 返回资源urlSchemeTask.didReceive(response)urlSchemeTask.didReceive(data)urlSchemeTask.didFinish()}task.resume()}
}class ResourceDownloader {static let shared = ResourceDownloader()private init() {}func downloadResources() {let resources = [URL(string: "https://www.example.com/styles.css")!,URL(string: "https://www.example.com/script.js")!,URL(string: "https://www.example.com/image.png")!]for resource in resources {downloadResource(from: resource)}}private func downloadResource(from url: URL) {let task = URLSession.shared.downloadTask(with: url) { localURL, response, error inguard let localURL = localURL else { return }do {let data = try Data(contentsOf: localURL)self.cacheResource(data: data, url: url)} catch {print("Failed to load resource: \(error)")}}task.resume()}func cacheResource(data: Data, url: URL) {let cacheDirectory = FileManager.default.urls(for: .cachesDirectory, in: .userDomainMask).first!let fileURL = cacheDirectory.appendingPathComponent(url.lastPathComponent)do {try data.write(to: fileURL)print("Resource cached: \(fileURL)")} catch {print("Failed to cache resource: \(error)")}}func getCachedResource(for url: URL) -> Data? {let cacheDirectory = FileManager.default.urls(for: .cachesDirectory, in: .userDomainMask).first!let fileURL = cacheDirectory.appendingPathComponent(url.lastPathComponent)return try? Data(contentsOf: fileURL)}
}
在应用启动时预加载资源
@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {var window: UIWindow?func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {// 预加载资源ResourceDownloader.shared.downloadResources()return true}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/27572.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

实现搜索功能中搜索内容高亮效果,本文通过fuzzysort库方案实现

目录 一&#xff1a;fuzzysort1.fuzzysort 介绍&#xff1a;2.需求所用方法介绍:gohighlight 3.效果实现 一&#xff1a;fuzzysort 1.fuzzysort 介绍&#xff1a; fuzzysort 是一个 JavaScript 库&#xff0c;用于对字符串数组进行模糊搜索和排序。它特别适用于自动补全&#…

Docker安装Nginx(各种错误版)

Docker安装-CSDN博客 安装启动Docker之后 docker run -d -p 81:81 --name nginx nginx 这样没有指定版本 docker run&#xff1a;启动一个新的容器。-d&#xff1a;以分离模式运行容器&#xff08;后台运行&#xff09;。-p 81:81&#xff1a;将主机的 81 端口映射到容器的 …

【网络安全学习】使用Kali做渗透情报收集-01-<域名信息主机信息>

1.收集开源情报 开源情报(Open Source Intelligence&#xff0c;OSINT)是指从各种公开的渠道中寻找和获取有价值的信息 如&#xff1a;互联网、媒体、社交网络、公共数据库等开源情报具有以下特点&#xff1a; - 丰富性&#xff1a;开源情报涵盖了各种类型和领域的信息 - 可…

Linux---系统的初步学习【项目一:Linux操作系统的安装与配置】

项目一 Linux操作系统的安装与配置 1.1 项目知识准备 1.1.1 操作系统是什么&#xff1f; ​ 操作系统&#xff08;Operating System&#xff0c;OS&#xff09;是管理计算机硬件与软件资源的计算机程序。操作系统需要处理如管理硬件、决定程序运行的优先次序、管理文件系统等…

WPF中的隧道路由和冒泡路由事件

文章目录 简介&#xff1a;一、事件最基本的用法二、理解路由事件 简介&#xff1a; WPF中使用路由事件升级了传统应用开发中的事件&#xff0c;在WPF中使用路由事件能更好的处理事件相关的逻辑&#xff0c;我们从这篇开始整理事件的用法和什么是直接路由&#xff0c;什么是冒…

WDF驱动开发-同步技术

使用自动同步 基于框架的驱动程序中几乎所有的代码都驻留在事件回调函数中。 框架会自动同步驱动程序的大部分回调函数&#xff0c;如下所示&#xff1a; 框架始终将 常规设备对象、 功能设备对象 (FDO) 和 物理设备对象 (PDO) 事件回调函数同步&#xff0c;以便每个设备一次…

Java高阶数据结构-----并查集(详解)

目录 &#x1f9d0;一.并查集的基本概念&实例&#xff1a; &#x1f92a;二.并查集代码&#xff1a; &#x1f602;三&#xff1a;并查集的一些习题&#xff1a; A.省份数量 B.等式方程的可满足性 &#x1f9d0;一.并查集的基本概念&实例&#xff1a; 并查集概念&…

向量化在人工智能领域的深度实践:技术革新与效率提升

在人工智能&#xff08;AI&#xff09;的飞速发展中&#xff0c;向量化技术作为一种基础且关键的数据处理手段&#xff0c;正日益受到广泛关注。向量化是将文本、图像、声音等数据转换为数值向量的过程&#xff0c;这些向量能够表示原始数据的特征和语义信息&#xff0c;为深度…

13.ChatGPT 大模型训练核心技术

ChatGPT 大模型训练核心技术 从 GPT-3 到 ChatGPT 的大模型训练技术演进 基于RLHF训练大模型的三阶段 • Domain Specific Pre-Training: Fine-tune a pre-trained LLM on raw text with a Causal Language Modelling Objective.• Supervised fine-tuning: Fine-tune the do…

外网访问公司内网服务器?

【天联】组网天联可以解决不同地区电脑与电脑、设备与设备、电脑与设备之间的信息远程通信问题。在全国各主要节点部署加速服务器&#xff0c;实现在低带宽、跨运营商的网络环境下高速访问&#xff1b;这为公司内网服务器提供了一个可行的外网访问解决方案。 在现代办公环境中…

CANoe连接Option Scope使用方法

系列文章目录 文章目录 系列文章目录前言一、前提条件二、CANoe配置三、PicoScope接线四、CANoe捕捉报文五、眼图功能前言 本文档主要介绍如何使用CANoe Option .Scope捕获CAN总线上的物理波形,并利用眼图进行分析。 一、前提条件 使用CANoe Option .Scope,需要具备以下条件…

AI绘画入门教程(非常详细)从零基础入门到精通Midjourney提示词,咒语

Microorganisms infiltrating through brain-machine interfaces --v 6.0 Microorganisms infiltrating through brain-machine interfaces ,redpupil --v 6.0 Microorganisms infiltrating through brain-machine interfaces,billion girls dream --v 6.0 --niji 6 “动漫风”…

Qt信号槽的回调机制

问&#xff1a;Qt强大的地方在哪里&#xff1f; 答&#xff1a;跨平台、信号槽。。。 问&#xff1a;信号槽是什么&#xff1f; 答&#xff1a;回调函数 问&#xff1a;怎么个回调法子 答&#xff1a;。。。 成果 信号槽本身实现过程是有些复杂的&#xff0c;所以本人参考…

50【Aseprite 作图】模糊工具 笔刷

1 模糊工具 2 笔刷 然后 选中 后 Ctrl B&#xff0c;就变成笔刷了 可以按住shift &#xff0c;像画一条线一样 或者用矩形、圆形工具、油漆桶工具 在上方可以选择笔刷的不同形式&#xff0c;如果是“图案与来源对齐”&#xff0c;就是来源不变&#xff0c;笔刷不会覆盖之前…

每日5题Day24 - LeetCode 116 - 120

每一步向前都是向自己的梦想更近一步&#xff0c;坚持不懈&#xff0c;勇往直前&#xff01; 第一题&#xff1a;116. 填充每个节点的下一个右侧节点指针 - 力扣&#xff08;LeetCode&#xff09; /* // Definition for a Node. class Node {public int val;public Node left;…

LeetCode | 171.Excel表列序号

这道题涉及到字符串和进制转换&#xff0c;首先我们先创建一个A-Z到1-26的map映射&#xff0c;方便我们后续遍历字符串转换&#xff0c;然后对字符串从后往前遍历&#xff0c;依次加上对应权重&#xff0c;注意越往前的权重越大&#xff0c;要记得对应乘上26的对应方数 class …

Nginx 搭建 lnmp

一.编译安装Nginx 1.新建用户前期准备 官网下载nginx安装包 https://nginx.org/en/download.html yum -y install gcc pcre-devel openssl-devel zlib-devel openssl openssl-devel #安装依赖包 useradd -M -s /sbin/nologin nginx #新建nginx用户便于管理 2.切换到/opt…

自动控制理论---线性时不变系统的单位脉冲响应

1、实验设备 PC计算机1台&#xff0c;MATLAB软件1套。 2.实验目的&#xff1a; 学习并理解线性时不变系统的单位脉冲响应的计算方法。掌握MATLAB编程&#xff0c;计算整个系统的单位脉冲响应。 3.实验原理说明&#xff1a; 单位脉冲响应是指在输入信号为单位脉冲序列时&am…

酷开科技丨酷开系统大屏游戏新体验,夏日宅家娱乐新方案

随着夏日的临近&#xff0c;人们开始寻找各种方式来打发炎热天气中的空闲时间。不论是与朋友们聚会、追剧&#xff0c;还是与队友们一起沉浸在游戏中&#xff0c;酷开科技都能为你提供好的解决方案。如果你也渴望在家中享受激情四溢的游戏对战&#xff0c;那么酷开系统将是你的…

[Java基本语法] 继承与多态

&#x1f338;个人主页:https://blog.csdn.net/2301_80050796?spm1000.2115.3001.5343 &#x1f3f5;️热门专栏:&#x1f355; Collection与数据结构 (92平均质量分)https://blog.csdn.net/2301_80050796/category_12621348.html?spm1001.2014.3001.5482 &#x1f9c0;线程与…