带有自定义字体的 iOS Today Widget 由于内存错误而终止

标签 ios ios8-today-widget today-extension

今日小工具

我们有一个使用自定义字体的 iOS 8+ 应用程序。 TTF 文件与应用捆绑在一起。

我们现在正在制作一个今天的小部件(扩展),它需要使用相同的自定义字体才能正确显示内容。

TTF 文件本身为 142 KB。

在我的测试数据中,使用自定义字体只会绘制 3-4 个字符。

症状

问题是使用这种字体会使小部件使用太多内存,并且小部件会调用一些 didReceiveMemoryWarning 然后终止。

如果我们改用“HelveticaNeue”字体,一切运行正常,但有问题的字符是根据 HelveticaNeue 而不是自定义字体显示的。

在 iOS 模拟器中一切运行良好,但几个 Stackoverflow 问题/答案让我相信这是很正常的,iOS 内存保护机制只会在设备上启动。

在 iPhone 6 上,小部件被杀死,内存使用量约为 20 MB,因此我们不会在这里谈论太多。在 iPhone 4S 上,限制似乎更低。

问题

所以问题是是否有解决方法。或者可以调整或研究的自定义字体的某些属性。

让主应用程序以某种方式将字体预呈现为磁盘上可以由小部件加载的内容(png 文件?)是否有意义?如何做到这一点?

有什么方法建议或要研究的东西吗?

最佳答案

我们还没有找到减少字体所用内存的方法。

我们通过使用 ImageMagick 和 perl 脚本成功地解决了所有可能的大小和我们正在使用的字形的 png 文件。

png 文件放在一个目录结构中,其中包含字体名称和磅值。每个字形都有自己的 png,以十六进制 Unicode 代码点命名。

然后所有 png 文件都被放入 Xcode 项目中,这样最终会出现在包中。

在运行时,我们不使用字体来渲染,而是使用 [UIImage imageNamed:] 来渲染它。

该解决方案性能良好,并且在小部件中使用的内存量有限。

有几个缺点:

  1. 小部件和主应用程序包变得臃肿:添加了 1000 多个 png 文件(575 KB = 4.7 MB 磁盘空间)。我们尚不知道这会增加多少应用程序的分发大小。
  2. 我们失去了原始方法的灵 active 。新设备类型或更好地支持动态类型可能会导致需要更多尺寸,然后我们需要生成更多 png。
  3. 更大的错误风险

生成 png 的脚本是:

#!/usr/bin/perl

use File::Path qw(make_path);

$fontName = "SSSymboliconsBlock";
@sizes = (10, 11, 13, 16, 18);

foreach $size (@sizes) {
    $path = "fontCache/$fontName/$size";
    make_path($path);
    @glyphs = ("1f50d", "1f512", "1f511");

    foreach $glyphNo (@glyphs) {
        $glyph = chr(hex($glyphNo));
        system("convert -background none -fill black -font $fontName.ttf -pointsize $size label:\"$glyph\" $path/$glyphNo.png");
    }
}

加载图像是这样的:

- (UIImage *)loadImageForGlyph:(NSString *)glyph
                      fontName:(NSString *)fontName
                      fontSize:(CGFloat)fontSize
{
    // NSDictionary that translates from a glyph to a string with the hex
    // value of the code point.
    // e.g. glyph = @"🔍", codePoint = @"1f50d"
    NSString * codePoint = self.codePointByGlyph[glyph];
    NSString * path
    = [[[[@"fontCache" stringByAppendingPathComponent:fontName]
       stringByAppendingPathComponent:[@(fontSize) stringValue]]
        stringByAppendingPathComponent:codePoint]
       stringByAppendingPathExtension:@"png"];

    UIImage * img = [UIImage imageNamed:path];

    return img;
}

关于带有自定义字体的 iOS Today Widget 由于内存错误而终止,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29054792/

相关文章:

ios - 元视口(viewport)在 iOS 设备上的 iframe 中不起作用

ios - 如何查找并修复崩溃原因

ios - 从数组加载图像并一次显示一张

objective-c - 将应用程序扩展安装到设备?

ios - iOS 是否允许在应用程序内打开或关闭蜂窝数据?

ios - 新的 iOS 10 Today Widget/Extension 的高度是多少?

ios - 今天扩展在 iOS 14 测试版中不起作用

ios - 解析 JSON 并使用 Realm 保存

ios - 暂时禁用今日扩展

iOS 9 Today Widget 不调用 viewDidLoad