diff --git a/framework/ios/module/fontLoader/HippyFontLoaderModule.h b/framework/ios/module/fontLoader/HippyFontLoaderModule.h index 1877330655d..caf1450d957 100644 --- a/framework/ios/module/fontLoader/HippyFontLoaderModule.h +++ b/framework/ios/module/fontLoader/HippyFontLoaderModule.h @@ -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 /** @@ -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 diff --git a/framework/ios/module/fontLoader/HippyFontLoaderModule.mm b/framework/ios/module/fontLoader/HippyFontLoaderModule.mm index 0d5016721d7..822a4b954e7 100644 --- a/framework/ios/module/fontLoader/HippyFontLoaderModule.mm +++ b/framework/ios/module/fontLoader/HippyFontLoaderModule.mm @@ -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 @@ -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]; @@ -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]; @@ -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; } } @@ -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]; } }]; } diff --git a/renderer/native/ios/renderer/HippyFont.mm b/renderer/native/ios/renderer/HippyFont.mm index f242584a610..4b037678a40 100644 --- a/renderer/native/ios/renderer/HippyFont.mm +++ b/renderer/native/ios/renderer/HippyFont.mm @@ -206,12 +206,14 @@ + (UIFont *)updateFont:(UIFont *)font variant:(NSArray *)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 @@ -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