1

今日のウィジェット

カスタム フォントを使用する iOS 8 以降のアプリがあります。TTF ファイルはアプリにバンドルされています。

現在、コンテンツを適切に表示するために同じカスタム フォントを使用する必要がある今日のウィジェット (拡張機能) を作成中です。

TTF ファイル自体は 142 KB です。

私のテスト データでは、カスタム フォントを使用して描画された文字は 3 ~ 4 文字だけです。

症状

問題は、このフォントを使用するとウィジェットが大量のメモリを使用し、ウィジェットが didReceiveMemoryWarning 呼び出しをいくつか取得して終了することです。

代わりにフォント「HelveticaNeue」を使用すると、すべて正常に動作しますが、問題の文字はカスタム フォントではなく HelveticaNeue に従って表示されます。

iOS シミュレーターではすべて正常に動作しますが、いくつかの Stackoverflow の質問/回答から、これはごく普通のことであり、iOS メモリ ガード メカニズムはデバイス上でのみ有効になると思われます。

iPhone 6 では、約 20 MB のメモリ使用量でウィジェットが強制終了されるため、ここではあまり説明しません。iPhone 4S では、制限はさらに低いようです。

質問

したがって、問題は回避策があるかどうかです。または、微調整または調査できるカスタムフォントのプロパティ。

ウィジェットによってロードできるディスク上の何か (png ファイル?) にフォントを何らかの方法でメイン アプリに事前レンダリングさせることは理にかなっていますか? どうすればそれを行うことができますか?

アプローチや検討すべきことについて何か提案はありますか?

4

1 に答える 1

2

フォントが使用するメモリを削減する方法を見つけることができませんでした。

ImageMagick と perl スクリプトを使用して、使用しているすべての可能なサイズとグリフの png ファイルを生成することで、回避策に成功しました。

png ファイルは、フォント名とポイント サイズを含むディレクトリ構造に配置されます。各グリフには、16 進数の Unicode コードポイントにちなんで名付けられた独自の png という名前があります。

次に、すべての png ファイルが Xcode プロジェクトに配置され、この方法でバンドルにまとめられます。

実行時にフォントを使用して[UIImage imageNamed:]レンダリングする代わりに、それを実行してレンダリングします。

このソリューションは適切に機能し、ウィジェットで限られた量のメモリを使用します。

いくつかの欠点があります。

  1. ウィジェットとメインのアプリ バンドルが肥大化します。1000 を超える png ファイルが追加されます (ディスク上で 575 KB = 4.7 MB)。これがアプリの配布サイズにどれだけ追加されるかはまだわかっていません。
  2. 元のアプローチの柔軟性を失います。新しいデバイス タイプまたは動的タイプのサポートの向上により、より多くのサイズが必要になる可能性があり、さらに多くの 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;
}
于 2015-03-23T20:15:46.853 に答える