Skip to content

Commit

Permalink
fix(ios): remove IO operations from main thread and ensure thread safety
Browse files Browse the repository at this point in the history
  • Loading branch information
Cyunong committed Oct 22, 2024
1 parent 370f9ab commit 46d3540
Show file tree
Hide file tree
Showing 3 changed files with 79 additions and 17 deletions.
21 changes: 21 additions & 0 deletions framework/ios/module/fontLoader/HippyFontLoaderModule.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,12 @@ NS_ASSUME_NONNULL_BEGIN

HIPPY_EXTERN NSString *const HippyLoadFontNotification;

typedef NS_ENUM(NSInteger, HippyFontUrlState) {
HippyFontUrlLoading = 0,
HippyFontUrlLoaded = 1,
HippyFontUrlFailed = 2,
};

@interface HippyFontLoaderModule : NSObject<HippyBridgeModule>

/**
Expand All @@ -44,6 +50,21 @@ HIPPY_EXTERN NSString *const HippyLoadFontNotification;
*/
+ (void)registerFontIfNeeded:(NSString *)fontFamily;

/**
* Whether the font is downloading from the url.
*
* @param url - The font url needs to download from.
* @return Yes if the font is downloading from the url.
*/
+ (BOOL) isUrlLoading:(NSString *)url;

/**
* Get the serial queue in HippyFontLoaderModule for asyn serial operations.
*
* @return The serial dispatch_queue_t.
*/
+ (dispatch_queue_t) getFontSerialQueue;

@end

NS_ASSUME_NONNULL_END
55 changes: 46 additions & 9 deletions framework/ios/module/fontLoader/HippyFontLoaderModule.mm
Original file line number Diff line number Diff line change
Expand Up @@ -36,16 +36,20 @@
static NSUInteger const FontLoaderErrorDirectoryError = 2;
static NSUInteger const FontLoaderErrorRequestError = 3;
static NSUInteger const FontLoaderErrorRegisterError = 4;
static NSUInteger const FontLoaderErrorWriteFileError = 4;
NSString *const HippyFontDirName = @"HippyFonts";
NSString *const HippyFontUrlCacheName = @"urlToFile.plist";
NSString *const HippyFontFamilyCacheName = @"fontFaimilyToFiles.plist";

static dispatch_queue_t serialQueue;
static NSMutableDictionary *urlToFile;
static NSMutableDictionary *fontFamilyToFiles;
static NSMutableDictionary *urlLoadState;
static NSMutableArray *fontRegistered = [NSMutableArray array];
static NSString *fontDirPath;
static NSString *fontUrlCachePath;
static NSString *fontFamilyCachePath;
static NSMutableArray *fontRegistered = [NSMutableArray array];


@implementation HippyFontLoaderModule

Expand All @@ -65,11 +69,24 @@ - (instancetype)init {
fontDirPath = [cachesDirectory stringByAppendingPathComponent:HippyFontDirName];
fontUrlCachePath = [fontDirPath stringByAppendingPathComponent:HippyFontUrlCacheName];
fontFamilyCachePath = [fontDirPath stringByAppendingPathComponent:HippyFontFamilyCacheName];
serialQueue = dispatch_queue_create("com.tencent.hippy.FontLoaderQueue", DISPATCH_QUEUE_SERIAL);
});
}
return self;
}

+ (dispatch_queue_t) getFontSerialQueue {
return serialQueue;
}

+ (void) setUrl:(NSString *)url state:(HippyFontUrlState)state {
[urlLoadState setObject:@(state) forKey:url];
}

+ (BOOL) isUrlLoading:(NSString *)url {
return [[urlLoadState objectForKey:url] integerValue] == HippyFontUrlLoading;
}

+ (void) initDictIfNeeded {
if (fontFamilyToFiles == nil) {
fontFamilyToFiles = [NSMutableDictionary dictionaryWithContentsOfFile:fontFamilyCachePath];
Expand Down Expand Up @@ -182,8 +199,16 @@ - (void)cacheFontfamily:(NSString *)fontFamily url:(NSString *)url fileName:(NSS
}
return;
}
NSFileManager *fileManager = [NSFileManager defaultManager];

@synchronized (self) {
if ([HippyFontLoaderModule isUrlLoading:urlString]) {
resolve([NSString stringWithFormat:@"url \"%@\" is downloading!", urlString]);
return;
}
[HippyFontLoaderModule setUrl:urlString state:HippyFontUrlLoading];
}

NSFileManager *fileManager = [NSFileManager defaultManager];
if (![fileManager fileExistsAtPath:fontDirPath]) {
NSError *error;
[fileManager createDirectoryAtPath:fontDirPath withIntermediateDirectories:YES attributes:nil error:&error];
Expand All @@ -192,6 +217,7 @@ - (void)cacheFontfamily:(NSString *)fontFamily url:(NSString *)url fileName:(NSS
if (reject) {
reject(errorKey, @"directory create error", error);
}
[HippyFontLoaderModule setUrl:urlString state:HippyFontUrlFailed];
return;
}
}
Expand All @@ -206,20 +232,31 @@ - (void)cacheFontfamily:(NSString *)fontFamily url:(NSString *)url fileName:(NSS
completionHandler:^(NSData *data, NSDictionary *userInfo, NSURLResponse *response, NSError *error) {
__strong __typeof(weakSelf) strongSelf = weakSelf;
if (error) {
NSString *errorKey = [NSString stringWithFormat:@"%lu", FontLoaderErrorRequestError];
if (reject) {
NSString *errorKey = [NSString stringWithFormat:@"%lu", FontLoaderErrorRequestError];
reject(errorKey, @"font request error", error);
}
[HippyFontLoaderModule setUrl:urlString state:HippyFontUrlFailed];
return;
}
NSString *fileName = [fontFamily stringByAppendingFormat:@".%@", [response.suggestedFilename pathExtension]];
NSString *fontFilePath = [fontDirPath stringByAppendingPathComponent:fileName];
[data writeToFile:fontFilePath atomically:YES];
[strongSelf cacheFontfamily:fontFamily url:urlString fileName:fileName];
[[NSNotificationCenter defaultCenter] postNotificationName:HippyFontChangeTriggerNotification object:nil];
if (resolve) {
HippyLogInfo(@"download font file \"%@\" success!", fileName);
resolve(nil);
if ([data writeToFile:fontFilePath atomically:YES]) {
dispatch_async([HippyFontLoaderModule getFontSerialQueue], ^{
[strongSelf cacheFontfamily:fontFamily url:urlString fileName:fileName];
[[NSNotificationCenter defaultCenter] postNotificationName:HippyFontChangeTriggerNotification object:nil];
});
if (resolve) {
resolve([NSString stringWithFormat:@"download font file \"%@\" success!", fileName]);
}
[HippyFontLoaderModule setUrl:urlString state:HippyFontUrlLoaded];
}
else {
if (reject) {
NSString *errorKey = [NSString stringWithFormat:@"%lu", FontLoaderErrorWriteFileError];
reject(errorKey, @"font request error", error);
}
[HippyFontLoaderModule setUrl:urlString state:HippyFontUrlFailed];
}
}];
}
Expand Down
20 changes: 12 additions & 8 deletions renderer/native/ios/renderer/HippyFont.mm
Original file line number Diff line number Diff line change
Expand Up @@ -206,12 +206,14 @@ + (UIFont *)updateFont:(UIFont *)font
variant:(NSArray<NativeRenderFontVariantDescriptor *> *)variant
scaleMultiplier:(CGFloat)scaleMultiplier {
// Defaults
if (url) {
NSString *fontPath = [HippyFontLoaderModule getFontPath:url];
if (!fontPath && family) {
NSDictionary *userInfo = @{@"fontUrl": url, @"fontFamily": family};
[[NSNotificationCenter defaultCenter] postNotificationName:HippyLoadFontNotification object:nil userInfo:userInfo];
}
if (url && ![HippyFontLoaderModule isUrlLoading:url]) {
dispatch_async([HippyFontLoaderModule getFontSerialQueue], ^{
NSString *fontPath = [HippyFontLoaderModule getFontPath:url];
if (!fontPath && family) {
NSDictionary *userInfo = @{@"fontUrl": url, @"fontFamily": family};
[[NSNotificationCenter defaultCenter] postNotificationName:HippyLoadFontNotification object:nil userInfo:userInfo];
}
});
}

// Defaults
Expand Down Expand Up @@ -251,8 +253,10 @@ + (UIFont *)updateFont:(UIFont *)font

BOOL didFindFont = NO;

if (fontNamesForFamilyName(familyName).count == 0) {
[HippyFontLoaderModule registerFontIfNeeded:familyName];
if (fontNamesForFamilyName(familyName).count == 0) {
dispatch_async([HippyFontLoaderModule getFontSerialQueue], ^{
[HippyFontLoaderModule registerFontIfNeeded:familyName];
});
}

// Handle system font as special case. This ensures that we preserve
Expand Down

0 comments on commit 46d3540

Please sign in to comment.