Question

We bundle a lot of fonts with our iOS app, and we put them all in UIAppFonts for faster loading.
(We're using them inside UIWebView and it's much faster than using loading files with @font-face).

However this lead me to occasionally get this kind of warning:

Mar 13 23:07:16 iPad afcd[2582] <Error>: Max open files: 78
Mar 13 23:07:17 iPad mobile_house_arrest[2584] <Error>: Max open files: 78
Mar 13 23:07:17 iPad mobile_house_arrest[2586] <Error>: Max open files: 78
Mar 13 23:07:17 iPad mobile_house_arrest[2587] <Error>: Max open files: 78
Mar 13 23:07:17 iPad mobile_house_arrest[2588] <Error>: Max open files: 78

This also correlated with I/O exceptions when opening files.

I used this snippet to find out the leaking files and it looks like iOS keeps open file descriptors for every font listed in UIAppFonts throughout the whole lifetime of the application.

File Descriptor 8 number 9 in use for: Fonts/ABeeZee-Regular.ttf
File Descriptor 9 number 10 in use for: Fonts/ABeeZee-Regular.ttf
File Descriptor 10 number 11 in use for: Fonts/ABeeZee-Italic.ttf
File Descriptor 11 number 12 in use for: Fonts/ABeeZee-Italic.ttf
File Descriptor 12 number 13 in use for: Fonts/AmaticSC-Regular.ttf
File Descriptor 13 number 14 in use for: Fonts/AmaticSC-Regular.ttf
File Descriptor 14 number 15 in use for: Fonts/AmaticSC-Bold.ttf
File Descriptor 15 number 16 in use for: Fonts/AmaticSC-Bold.ttf
File Descriptor 16 number 17 in use for: Fonts/AnonymousPro-Bold.ttf
File Descriptor 17 number 18 in use for: Fonts/AnonymousPro-Bold.ttf
File Descriptor 18 number 19 in use for: Fonts/AnonymousPro-Regular.ttf
File Descriptor 19 number 20 in use for: Fonts/AnonymousPro-Regular.ttf

For us, it means about a hundred open file descriptors, although not more than five of UIAppFonts are being used at the moment. Sometimes, duplicate entries show up.

Is there anyway to forcibly close file descriptors for UIAppFonts I'm not using at the moment?

If not, is there an alternative way of keeping local fonts available to UIWebView without resorting to @font-face which is slow?

Was it helpful?

Solution

If not, is there an alternative way of keeping local fonts available to UIWebView without resorting to @font-face which is slow?

Turns out, there is.

We solved the problem by registering fonts using CTFontManagerRegisterFontsForURL and unregistering them with CTFontManagerUnregisterFontsForURL. This keeps them available for UIWebView, given that you always register fonts before using them in font-family.

OTHER TIPS

I was having trouble with closing file descriptors associated with a Sprite Kit action,

playSoundFileNamed:

They never close. So they eat up file descriptors until the app crashes. I figured out a way to close them. I don't see why it wouldn't work for your UIAppFonts.

I modified the snippet you referenced in your question. This is my modified version,

#import <sys/types.h>
#import <fcntl.h>
#import <errno.h>
#import <sys/param.h>


-(void)closeFileDescriptorsForSounds
{
    int flags;
    int fd;
    char buf[MAXPATHLEN+1] ;
    int n = 1 ;

    for (fd = 0; fd < (int) FD_SETSIZE; fd++) {
        errno = 0;
        flags = fcntl(fd, F_GETFD, 0);
        if (flags == -1 && errno) {
            if (errno != EBADF) {
                return ;
            }
            else
                continue;
        }
        fcntl(fd , F_GETPATH, buf ) ;
        NSLog( @"File Descriptor %d number %d in use for: %s",fd,n , buf ) ;
        ++n ;

// My modifications to the snippet...

        NSString *str = [NSString stringWithUTF8String:buf];
        NSString *theFileName = [str lastPathComponent];

        if ([theFileName isEqualToString:@"LoudBang.mp3"])
        {
            NSLog(@"FD is LoudBang");
            NSFileHandle *loudBangHandle = [[NSFileHandle alloc] initWithFileDescriptor:fd closeOnDealloc:YES];
        }
        else if ([theFileName isEqualToString:@"QuietBang.mp3"])
        {
            NSLog(@"FD is QuietBang");
            NSFileHandle *quietBangHandle = [[NSFileHandle alloc] initWithFileDescriptor:fd closeOnDealloc:YES];
        }
    }
}

I converted buf to a string and then isolated the file name. Then I compared the file name to a known file I want to close. When a file I want to close is found the code creates an NSFileHandle around the file descriptor using the following,

NSFileHandle *loudBangHandle = [[NSFileHandle alloc] initWithFileDescriptor:fd closeOnDealloc:YES];

This init specifically closes the file descriptor on dealloc of the NSFileHandle (which will be almost immediately).

Let us know if it works for your UIAppFonts.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top