We have an iOS 8+ app that uses a custom font. The TTF file is bundled with the app.
We are now in the process of making a today widget (extension) that needs to use the same custom font in order to properly show the contents.
The TTF file itself is 142 KB.
With my test data there will be only 3-4 characters drawn using the custom font.
The problem is that the use of this font makes the widget use too much memory and the widget gets a few didReceiveMemoryWarning calls and is then terminated.
If we use the font "HelveticaNeue" instead everything runs fine but the characters in question are of cause show according to HelveticaNeue and not the custom font.
Everything runs fine in the iOS simulator, but several Stackoverflow questions/answers lead me to believe this is quite normal and that the iOS memory guard mechanism will only kick in on device.
On an iPhone 6 the widget is killed with a memory usage around 20 MB so we are not talking about a lot here. On an iPhone 4S the limit seems to be even lower.
So the question is if there is a work-around. Or some property of the custom font that could be tweaked or looked into.
Would it make sense to have the main app somehow pre-render the font into something (png files?) on disk that could be loaded by the widget? How would one do that?
Any suggestions for an approach or something to look into?
We have not been able to find a way to reduce the memory used by the font.
We have succeeded with a work-around by using ImageMagick and a perl script to generate png files for all the possible sizes and glyphs that we are using.
The png files are put in a directory structure with font name and point size. Each glyph has its own png named that is named after the hex Unicode codepoint.
All the png files are then put into the Xcode project and this way ends up in the bundle.
At run-time instead of using the font to render we do a [UIImage imageNamed:]
and render that instead.
The solution performs well and uses limited amount of memory in the widget.
There are several drawbacks:
The script for generating the pngs is:
#!/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");
}
}
To load the image it is something like this:
- (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;
}