【问题标题】:Xcode: Load custom locally stored font for remote content in WKWebViewXcode:为 WKWebView 中的远程内容加载自定义本地存储的字体
【发布时间】:2020-10-25 05:01:26
【问题描述】:

我正在使用最新版本的XcodeSwift

我有以下代码来加载 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 字符串,并且我知道如何在没有本地存储的字体的情况下加载远程内容。但我不知道如何加载 remote 内容 本地存储的字体。

我试过了:

webView.load(request, baseURL: Bundle.main.resourceURL)

但这不起作用。它会引发错误。

我尝试了很多,但没有成功。我的最后一个想法是从远程内容中获取源代码,将其转换为字符串,为其添加font-face 样式并使用webView.loadHTMLString 加载它。这将允许我显示远程内容,同时仍然能够使用webView.loadHTMLString(html, baseURL: Bundle.main.resourceURL) 加载它以将本地存储的字体传递给它。

真的没有其他方法可以做到这一点吗?使用webView.load(request)时有没有办法使用我本地存储的字体?

【问题讨论】:

    标签: ios swift xcode font-face wkwebview


    【解决方案1】:

    我现在找到了解决方案。也许不是最好的,但它正在工作。

    首先,我使用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;
    }
    

    我使用此代码(上面来自转换器的代码)将名为 fonts.css 的文件导入/嵌入到我的 Xcode 项目中。导入/嵌入时应激活Add to targets

    在我的 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)文件中,该文件是从我的 Web 服务器远程加载的:

    <style>
    *   {
        font-family:'Blastimo';
    }
    </style>
    

    注意: 您正在远程加载的文件需要有&lt;head&gt;&lt;/head&gt; 元素,因为字体是在此结束时注入的。

    【讨论】:

      【解决方案2】:

      使用自定义字体的另一种方法是使用this 之类的转换器将字体文件转换为.MOBILECONFIG 文件。然后您可以在设备上打开这个.MOBILECONFIG 文件并安装字体。

      【讨论】:

        猜你喜欢
        • 2020-10-25
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-01-23
        • 2020-04-09
        • 2014-01-27
        • 2014-11-05
        相关资源
        最近更新 更多