61

我在我的应用程序中使用自定义字体。它们被复制到 bundle 并硬编码到 appName-info.plist。这种字体在整个应用程序和 UIWebView 中都能完美运行。

我正在加载 htmlString [webView loadHTMLString:htmlString baseURL:nil]; 我在 webView 中使用这个字体和 css: fontFamily: fontName

但是当我尝试使用 WkWebView 自定义字体时不起作用。WkWebView 显示随机的默认字体。

我尝试使用基本 url 中的主包路径加载它,并在 css 中使用 font-face - WkWebView 仍然显示随机字体。

如何使自定义字体在 WKWebView 中工作?

4

5 回答 5

56

我遇到了同样的问题,在我的情况下,我可以在不使用base64 编码GCDWebServer的情况下修复

设想:

  • WkWebView 加载是通过字符串 html
  • WkWebView 正在使用本地 .css
  • 字体是本地的,并在顶级项目中添加
  • 字体条目在 appName-info.plist 中的 key UIAppFonts/下提供Fonts provided by application注意:我们需要做这个舞蹈,因为 WKWebView 忽略了这个 key,但声明它仍然是一个好主意,以便您可以在本机控件中使用字体)

解决方案:

在顶层的 .css 中添加字体,如下所示

@font-face
{
    font-family: 'FontFamily';
    src: local('FontFamily'),url('FontFileName.otf') format('opentype');
}

演示项目:

GitHub 项目链接

注意:新的演示应用程序运行可能需要 2-3 秒,我已经测试了它的长 html 字符串,它与 UIWebView 相同,没有滞后。相同的字体在 WKWebView 中可能看起来比 UIWebView 小一些。

于 2016-02-24T20:08:22.950 回答
42

假设您将字体作为复制到目标包的资源嵌入到应用程序中,您可以通过将 NSURL 作为 baseURL 传递给 WKWebView 对字体的访问权限

NSString *bundlePath = [[NSBundle mainBundle] bundlePath];
NSURL *bundleUrl = [NSURL fileURLWithPath:bundlePath];
[self.webView loadHTMLString:HTML baseURL:bundleUrl];

并在没有任何前面的路径元素的情况下定义字体 url,这反过来又使 WKWebKit 前置 baseURL

<style>
  @font-face { font-family: 'Custom Font'; src: url('CustomFont.ttf'); }
  ...
</style>
于 2016-04-08T09:15:53.120 回答
22

由于我不想为此使用另一个第三方,并且由于我正在构建 html 字符串本身,所以我采用了使用字体的第一部分,而不是使用远程或本地文件的 url,我将字体转换为base64。

CSS看起来像这样:

@font-face {
    font-family: 'FONTFAMILY';
    src: url(data:font/ttf;base64,FONTBASE64) format('truetype');
}

您可以将 FONTFAMILY 替换为您需要的系列,并将 FONTBASE64 替换为从字体生成的 base 64 字符串。

如果您需要在应用程序中创建 base64 字符串,您可以使用它,只需提供文件名和类型(我也使用它来获取其他文件,因此它更通用,您可以删除 ofType 参数并使用 @"ttf"反而):

- (NSString*)getBase64FromFile:(NSString*)fileName ofType:(NSString*)type
{
    NSString * filePath = [[NSBundle mainBundle] pathForResource:fileName ofType:type];

    // Create NSData object
    NSData *nsdata = [NSData dataWithContentsOfFile:filePath];

    // Get NSString from NSData object in Base64
    NSString *base64Encoded = [nsdata base64EncodedStringWithOptions:0];

    return base64Encoded;
}

如果您只想执行一次然后将其保存在某个文件中,您可以使用任何将文件转换为 base64 的在线网站,例如:http ://www.opinionatedgeek.com/dotnet/tools/base64encode/

于 2014-09-27T18:49:19.593 回答
11

更新:现在可以使用WKURLSchemeHandler.

@interface MySchemeHandler : NSObject <WKURLSchemeHandler>
@end

@implementation MySchemeHandler

- (void)webView:(nonnull WKWebView *)webView startURLSchemeTask:(nonnull id<WKURLSchemeTask>)urlSchemeTask
{
  NSURL *url = urlSchemeTask.request.URL;
  NSString *mimeType = [NSString stringWithFormat:@"text/%@", url.pathExtension]; //or whatever you need
  NSURLResponse *response = [[NSURLResponse alloc] initWithURL:url MIMEType:mimeType expectedContentLength:-1 textEncodingName:nil];
  [urlSchemeTask didReceiveResponse:response];
  NSData *data = [self getResponseData];
  [urlSchemeTask didReceiveData:data];
  [urlSchemeTask didFinish];
}
@end

在配置您的WKWebView实例时:

WKWebViewConfiguration *config = [[WKWebViewConfiguration alloc] init];
MySchemeHandler *handler = [[MySchemeHandler alloc] init];
[config setURLSchemeHandler:handler forURLScheme:@"myScheme"];
//now pass the config to your WKWebView

------旧答案----------

我的猜测是WKWebView无法再访问特定于应用程序的字体,因为它现在处于单独的进程 (XPC) 中。

我通过@font-face在 CSS 中添加带有声明的字体来解决这个问题。有关如何执行此操作的详细信息,请参见此处。

例子:

@font-face
{
  font-family: "MyFontFace";
  src:url('url-to-font.ttf');
}

//And if you have a font with files with different variants, add this:
@font-face
{
  font-family: "MyFontFace";
  src:url('url-to-italic-variant.ttf');
  font-style:italic;
}

但这将引用一个本地文件,这是WKWebView无法做到的(我假设您已经发现了这一点,因为您正在加载 HTML 字符串而不是本地文件)。根据对此问题的评论,我能够使用GCDWebServer让我的本地 HTML 文件正常工作。在您的应用程序委托中,根据 GitHub 上的 GCDWebServer wiki 将相关文件添加到您的项目后:

GCDWebServer *server = [[[GCDWebServer alloc]init]autorelease];
NSString *bundlePath = [[NSBundle mainBundle] bundlePath];
[server addGETHandlerForBasePath:@"/"
   directoryPath:bundlePath indexFilename:nil
   cacheAge:0 allowRangeRequests:YES];
[server startWithPort:8080 bonjourName:nil];

现在您可以像这样引用捆绑包中命名的 HTML 文件test.html

NSString *path = @"http://localhost:8080/test.html";
NSURL *url = [NSURL URLWithString:path];
NSURLRequest *request = [NSURLRequest requestWithURL:url];
[myWebView loadRequest:request];

将上述@font-face声明放在style您的 HTML 文件中的一个元素中(或者如果您真的只需要加载一个字符串,则放在您的 HTML 字符串中),您应该很高兴。

于 2014-09-11T22:52:42.393 回答
7

这是@Henrik Hartz 的 swift 3 版本的真棒答案:

loadHTMLString(htmlString, baseURL: NSURL.fileURL(withPath: Bundle.main.bundlePath))
于 2017-09-06T14:03:31.143 回答