Xcode: 为 WKWebView 中的远程内容加载自定义本地存储的字体
Xcode: Load custom locally stored font for remote content in WKWebView
我正在使用最新版本的 Xcode
和 Swift
。
我有以下代码来加载 HTML 字符串并使用自定义字体,我之前在 Xcode 中导入:
let html = """
<html>
<body>
<head>
<style>
@font-face
{
font-family: 'Blastimo';
src: local('Blastimo'), url('Blastimo.ttf') format('truetype');
}
</style>
</head>
<h1 style="font-family:'Blastimo';font-size:50px;">This is my test!</h1>
</body>
</html>
"""
webView.loadHTMLString(html, baseURL: Bundle.main.resourceURL)
以下代码允许我加载远程内容,例如来自我的网络服务器:
if let url = URL(string: "https://www.example.com") {
let request = URLRequest(url: url)
webView.load(request)
}
但是,我想要达到的是:加载远程内容,如在第二个代码中,但将我本地存储的自定义字体传递给它,如在第一个代码中。
意思是:我知道如何使用本地存储的字体加载 HTML 字符串,并且我知道如何在没有本地存储的字体的情况下加载远程内容。但是我不知道如何使用本地存储的字体加载远程内容。
我试过了:
webView.load(request, baseURL: Bundle.main.resourceURL)
但这不起作用。它会引发错误。
我尝试了很多但没有成功。我最后的想法是从远程内容中获取源代码,将其转换为字符串,为其添加 font-face
样式并使用 webView.loadHTMLString
加载它。这将允许我显示远程内容,同时仍然能够使用 webView.loadHTMLString(html, baseURL: Bundle.main.resourceURL)
加载它以将本地存储的字体传递给它。
真的没有别的办法吗?使用webView.load(request)
时是否无法使用我本地存储的字体?
我现在找到了解决办法。也许不是最好的,但它正在工作。
首先,我使用 this 转换器将 Blastimo.ttf
文件转换为 base64 编码的 CSS 嵌入字体。
这给了我以下(或类似):
@font-face {
font-family: 'Blastimo';
src: url(data:application/x-font-woff;charset=utf-8;base64,HERE_COMES_THE_QUITE_LONG_BASE64_CODE_CREATED_BY_THE_CONVERTER) format('woff');
font-weight: normal;
font-style: normal;
}
我 imported/embedded 一个名为 fonts.css
的文件,其中包含此代码(上面来自转换器的代码)到我的 Xcode 项目。 Add to targets
应在 importing/embedding.
时激活
在我的 ViewController.swift
文件中,我有以下代码(例如在 viewDidLoad()
中)加载远程内容并调用本地 CSS 文件的函数:
if let url = URL(string: "https://www.example.com") {
let request = URLRequest(url: url)
webView.load(request)
}
injectToPage()
此外,这三个函数必须添加到 ViewController.swift
文件的某处:
private func readFileBy(name: String, type: String) -> String {
guard let path = Bundle.main.path(forResource: name, ofType: type) else {
return "Failed to find path"
}
do {
return try String(contentsOfFile: path, encoding: .utf8)
} catch {
return "Unkown Error"
}
}
func injectToPage() {
let cssFile = readFileBy(name: "fonts", type: "css")
let cssStyle = """
javascript:(function() {
var parent = document.getElementsByTagName('head').item(0);
var style = document.createElement('style');
style.innerHTML = window.atob('\(encodeStringTo64(fromString: cssFile)!)');
parent.appendChild(style)})()
"""
let cssScript = WKUserScript(source: cssStyle, injectionTime: .atDocumentEnd, forMainFrameOnly: false)
webView.configuration.userContentController.addUserScript(cssScript)
}
private func encodeStringTo64(fromString: String) -> String? {
let plainData = fromString.data(using: .utf8)
return plainData?.base64EncodedString(options: [])
}
现在,尽管内容是远程加载的,但我可以在 WKWebView
中使用应用程序中本地存储的字体。
就我而言,我将其添加到(html 或 php)文件,该文件是从我的网络服务器远程加载的:
<style>
* {
font-family:'Blastimo';
}
</style>
注:
您正在远程加载的文件需要有 <head></head>
元素,因为字体是在这个末尾注入的。
另一种使用自定义字体的方法是使用 this 之类的转换器将字体文件转换为 .MOBILECONFIG
文件。然后您可以在设备上打开此 .MOBILECONFIG
文件并安装字体。
我正在使用最新版本的 Xcode
和 Swift
。
我有以下代码来加载 HTML 字符串并使用自定义字体,我之前在 Xcode 中导入:
let html = """
<html>
<body>
<head>
<style>
@font-face
{
font-family: 'Blastimo';
src: local('Blastimo'), url('Blastimo.ttf') format('truetype');
}
</style>
</head>
<h1 style="font-family:'Blastimo';font-size:50px;">This is my test!</h1>
</body>
</html>
"""
webView.loadHTMLString(html, baseURL: Bundle.main.resourceURL)
以下代码允许我加载远程内容,例如来自我的网络服务器:
if let url = URL(string: "https://www.example.com") {
let request = URLRequest(url: url)
webView.load(request)
}
但是,我想要达到的是:加载远程内容,如在第二个代码中,但将我本地存储的自定义字体传递给它,如在第一个代码中。
意思是:我知道如何使用本地存储的字体加载 HTML 字符串,并且我知道如何在没有本地存储的字体的情况下加载远程内容。但是我不知道如何使用本地存储的字体加载远程内容。
我试过了:
webView.load(request, baseURL: Bundle.main.resourceURL)
但这不起作用。它会引发错误。
我尝试了很多但没有成功。我最后的想法是从远程内容中获取源代码,将其转换为字符串,为其添加 font-face
样式并使用 webView.loadHTMLString
加载它。这将允许我显示远程内容,同时仍然能够使用 webView.loadHTMLString(html, baseURL: Bundle.main.resourceURL)
加载它以将本地存储的字体传递给它。
真的没有别的办法吗?使用webView.load(request)
时是否无法使用我本地存储的字体?
我现在找到了解决办法。也许不是最好的,但它正在工作。
首先,我使用 this 转换器将 Blastimo.ttf
文件转换为 base64 编码的 CSS 嵌入字体。
这给了我以下(或类似):
@font-face {
font-family: 'Blastimo';
src: url(data:application/x-font-woff;charset=utf-8;base64,HERE_COMES_THE_QUITE_LONG_BASE64_CODE_CREATED_BY_THE_CONVERTER) format('woff');
font-weight: normal;
font-style: normal;
}
我 imported/embedded 一个名为 fonts.css
的文件,其中包含此代码(上面来自转换器的代码)到我的 Xcode 项目。 Add to targets
应在 importing/embedding.
在我的 ViewController.swift
文件中,我有以下代码(例如在 viewDidLoad()
中)加载远程内容并调用本地 CSS 文件的函数:
if let url = URL(string: "https://www.example.com") {
let request = URLRequest(url: url)
webView.load(request)
}
injectToPage()
此外,这三个函数必须添加到 ViewController.swift
文件的某处:
private func readFileBy(name: String, type: String) -> String {
guard let path = Bundle.main.path(forResource: name, ofType: type) else {
return "Failed to find path"
}
do {
return try String(contentsOfFile: path, encoding: .utf8)
} catch {
return "Unkown Error"
}
}
func injectToPage() {
let cssFile = readFileBy(name: "fonts", type: "css")
let cssStyle = """
javascript:(function() {
var parent = document.getElementsByTagName('head').item(0);
var style = document.createElement('style');
style.innerHTML = window.atob('\(encodeStringTo64(fromString: cssFile)!)');
parent.appendChild(style)})()
"""
let cssScript = WKUserScript(source: cssStyle, injectionTime: .atDocumentEnd, forMainFrameOnly: false)
webView.configuration.userContentController.addUserScript(cssScript)
}
private func encodeStringTo64(fromString: String) -> String? {
let plainData = fromString.data(using: .utf8)
return plainData?.base64EncodedString(options: [])
}
现在,尽管内容是远程加载的,但我可以在 WKWebView
中使用应用程序中本地存储的字体。
就我而言,我将其添加到(html 或 php)文件,该文件是从我的网络服务器远程加载的:
<style>
* {
font-family:'Blastimo';
}
</style>
注:
您正在远程加载的文件需要有 <head></head>
元素,因为字体是在这个末尾注入的。
另一种使用自定义字体的方法是使用 this 之类的转换器将字体文件转换为 .MOBILECONFIG
文件。然后您可以在设备上打开此 .MOBILECONFIG
文件并安装字体。