移动开发俱乐部

iOS 自定义字体内存泄漏( leak cycles)

2018-03-12  本文已影响9人  恩莱客

问题描述:工程中内存管理采用ARC方式,我们在使用自定义字体时内存存在持续增加不释放问题,Xcode Debug显示在使用字体时,Memory升降不是平衡的(切换界面),造成内存逐渐累积,而我们工程中使用自定义字体的地方非常多,内存飙升的可怕。使用Instrument中的leak工具检测(如下图),FontFamily 方法中存在循环引用问题。

leak检测.png

leak cycles方法:

- (NSString *)fontFamilyWithFontPath{
   NSString *fontPath = [NSHomeDirectory() stringByAppendingString:[NSString
             stringWithFormat:@"/Documents/%@.ttf", _cssInfo.fontFamily]];
     NSData *dynamicFontData = [NSData dataWithContentsOfFile:fontPath];
    if (!dynamicFontData) {
        return@"";
    }
    CFErrorRef error = nil;
    CGDataProviderRef providerRef = CGDataProviderCreateWithCFData((__bridge CFDataRef)dynamicFontData);
    if (!providerRef) {
        CGDataProviderRelease(providerRef);
        return @"";
    }
    [UIFont familyNames];
    CGFontRef newFont = CGFontCreateWithDataProvider(providerRef);
    if (!newFont) {
        CGFontRelease(newFont);
        CGDataProviderRelease(providerRef);
        return @"";
    }
    if (!CTFontManagerRegisterGraphicsFont(newFont, &error)) {
        //注册失败
        CFStringRef errorDescription = CFErrorCopyDescription(error);
        CFRelease(errorDescription);
    }
    NSString *newFamilyName = CFBridgingRelease(CGFontCopyPostScriptName(newFont));
    CGDataProviderRelease(providerRef);
    CGFontRelease(newFont);
}

代码调整:去掉了dataWithContentsOfFile:获取data过程,而是直接使用URL获取字体数据。

  NSString *fontPath = [NSHomeDirectory() stringByAppendingString:[NSString
             stringWithFormat:@"/Documents/%@.ttf", _cssInfo.fontFamily]];
    if (!fontPath) {
        return @"";
    }
    //调整位置
    NSURL *fontUrl = [NSURL fileURLWithPath:fontPath];
    CGDataProviderRef fontDataProvider = CGDataProviderCreateWithURL((__bridge CFURLRef)fontUrl);
    if (!fontDataProvider) {
        CGDataProviderRelease(fontDataProvider);
        return @"";
    }
    [UIFont familyNames];
    CGFontRef fontRef = CGFontCreateWithDataProvider(fontDataProvider);
    if (!fontRef) {
        CGDataProviderRelease(fontDataProvider);
        CGFontRelease(fontRef);
        return @"";
    }
    CGDataProviderRelease(fontDataProvider);
    CTFontManagerUnregisterGraphicsFont(fontRef,nil);
    CTFontManagerRegisterGraphicsFont(fontRef, NULL);
    NSString *newFamilyName = CFBridgingRelease(CGFontCopyPostScriptName(fontRef));
    CGFontRelease(fontRef);

经过调整后,内存使用恢复正常。

上一篇下一篇

猜你喜欢

热点阅读