From d6aaacd7584331ac9fc1f537a0d22ebc90d8dc2b Mon Sep 17 00:00:00 2001 From: Dmitry Stadnik Date: Mon, 31 May 2021 18:19:10 +0500 Subject: [PATCH 1/2] feat: runInBackground thread for iOS --- ios/ChunkManager.mm | 141 ++++++++++++++++++++++++-------------------- 1 file changed, 76 insertions(+), 65 deletions(-) diff --git a/ios/ChunkManager.mm b/ios/ChunkManager.mm index bd42195df..651d5a524 100644 --- a/ios/ChunkManager.mm +++ b/ios/ChunkManager.mm @@ -29,87 +29,93 @@ @implementation ChunkManager withResolver:(RCTPromiseResolveBlock)resolve withRejecter:(RCTPromiseRejectBlock)reject) { - // Cast `RCTBridge` to `RCTCxxBridge`. - __weak RCTCxxBridge *bridge = (RCTCxxBridge *)_bridge; - - NSURL *chunkUrl = [NSURL URLWithString:chunkUrlString]; - - // Handle http & https - if ([[chunkUrl scheme] hasPrefix:@"http"]) { - if (fetch) { - [self downloadAndCache:chunkId chunkUrl:chunkUrl completionHandler:^(NSError *error) { - if (error) { - reject(ChunkDownloadFailure, error.localizedFailureReason, nil); - } else { - [self execute:bridge chunkId:chunkId url:chunkUrl withResolver:resolve withRejecter:reject]; - } - }]; - } else { - [self execute:bridge chunkId:chunkId url:chunkUrl withResolver:resolve withRejecter:reject]; - } + [self runInBackground:^(){ + // Cast `RCTBridge` to `RCTCxxBridge`. + __weak RCTCxxBridge *bridge = (RCTCxxBridge *)_bridge; - } else if ([[chunkUrl scheme] isEqualToString:@"file"]) { - [self executeFromFilesystem:bridge url:chunkUrl withResolver:resolve withRejecter:reject]; + NSURL *chunkUrl = [NSURL URLWithString:chunkUrlString]; - } else { - reject(UnsupportedScheme, - [NSString stringWithFormat:@"Scheme in URL '%@' is not supported", chunkUrlString], nil); - } + // Handle http & https + if ([[chunkUrl scheme] hasPrefix:@"http"]) { + if (fetch) { + [self downloadAndCache:chunkId chunkUrl:chunkUrl completionHandler:^(NSError *error) { + if (error) { + reject(ChunkDownloadFailure, error.localizedFailureReason, nil); + } else { + [self execute:bridge chunkId:chunkId url:chunkUrl withResolver:resolve withRejecter:reject]; + } + }]; + } else { + [self execute:bridge chunkId:chunkId url:chunkUrl withResolver:resolve withRejecter:reject]; + } + + } else if ([[chunkUrl scheme] isEqualToString:@"file"]) { + [self executeFromFilesystem:bridge url:chunkUrl withResolver:resolve withRejecter:reject]; + + } else { + reject(UnsupportedScheme, + [NSString stringWithFormat:@"Scheme in URL '%@' is not supported", chunkUrlString], nil); + } + }]; } RCT_EXPORT_METHOD(preloadChunk:(nonnull NSString*)chunkId chunkUrl:(nonnull NSString*)chunkUrlString fetch:(BOOL)fetch withResolver:(RCTPromiseResolveBlock)resolve - withRejecter:(RCTPromiseRejectBlock)reject) { - if (!fetch) { - // Do nothing, chunk is already preloaded - resolve(nil); - } else { - NSURL *chunkUrl = [NSURL URLWithString:chunkUrlString]; - if ([[chunkUrl scheme] hasPrefix:@"http"]) { - [self downloadAndCache:chunkId chunkUrl:chunkUrl completionHandler:^(NSError *error) { - if (error) { - reject(ChunkDownloadFailure, error.localizedFailureReason, nil); - } else { - resolve(nil); - } - }]; + withRejecter:(RCTPromiseRejectBlock)reject) +{ + [self runInBackground:^(){ + if (!fetch) { + // Do nothing, chunk is already preloaded + resolve(nil); } else { - reject(UnsupportedScheme, - [NSString stringWithFormat:@"Scheme in URL '%@' is not supported", chunkUrlString], nil); + NSURL *chunkUrl = [NSURL URLWithString:chunkUrlString]; + if ([[chunkUrl scheme] hasPrefix:@"http"]) { + [self downloadAndCache:chunkId chunkUrl:chunkUrl completionHandler:^(NSError *error) { + if (error) { + reject(ChunkDownloadFailure, error.localizedFailureReason, nil); + } else { + resolve(nil); + } + }]; + } else { + reject(UnsupportedScheme, + [NSString stringWithFormat:@"Scheme in URL '%@' is not supported", chunkUrlString], nil); + } } - } - + }]; } RCT_EXPORT_METHOD(invalidateChunks:(nonnull NSArray*)chunks withResolver:(RCTPromiseResolveBlock)resolve - withRejecter:(RCTPromiseRejectBlock)reject) { - NSFileManager* manager = [NSFileManager defaultManager]; - NSString* chunksDirecotryPath = [self getChunksDirectoryPath]; - - NSError *error; - if (chunks.count == 0 && [manager fileExistsAtPath:chunksDirecotryPath]) { - [manager removeItemAtPath:chunksDirecotryPath error:&error]; - } else { - for (int i = 0; i < chunks.count; i++) { - NSString* chunkFilePath = [self getChunkFilePath:chunks[i]]; - if ([manager fileExistsAtPath:chunkFilePath]) { - [manager removeItemAtPath:[self getChunkFilePath:chunks[i]] error:&error]; - } - if (error != nil) { - break; + withRejecter:(RCTPromiseRejectBlock)reject) +{ + [self runInBackground:^(){ + NSFileManager* manager = [NSFileManager defaultManager]; + NSString* chunksDirecotryPath = [self getChunksDirectoryPath]; + + NSError *error; + if (chunks.count == 0 && [manager fileExistsAtPath:chunksDirecotryPath]) { + [manager removeItemAtPath:chunksDirecotryPath error:&error]; + } else { + for (int i = 0; i < chunks.count; i++) { + NSString* chunkFilePath = [self getChunkFilePath:chunks[i]]; + if ([manager fileExistsAtPath:chunkFilePath]) { + [manager removeItemAtPath:[self getChunkFilePath:chunks[i]] error:&error]; + } + if (error != nil) { + break; + } } } - } - - if (error != nil) { - reject(InvalidationFailure, error.localizedDescription, nil); - } else { - resolve(nil); - } - + + if (error != nil) { + reject(InvalidationFailure, error.localizedDescription, nil); + } else { + resolve(nil); + } + }]; } - (void)execute:(RCTCxxBridge *)bridge @@ -202,4 +208,9 @@ - (void)executeFromFilesystem:(RCTCxxBridge *)bridge } +- (void)runInBackground:(void(^)())callback +{ + dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), callback); +} + @end From a0e2a23691f9a0b6fdf6e89f9ad8e15008ae82a8 Mon Sep 17 00:00:00 2001 From: Dmitry Stadnik Date: Mon, 31 May 2021 18:38:56 +0500 Subject: [PATCH 2/2] fix: avoid unnecessarily spawning new threads --- ios/ChunkManager.mm | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/ios/ChunkManager.mm b/ios/ChunkManager.mm index 651d5a524..c70dea891 100644 --- a/ios/ChunkManager.mm +++ b/ios/ChunkManager.mm @@ -65,11 +65,11 @@ @implementation ChunkManager withResolver:(RCTPromiseResolveBlock)resolve withRejecter:(RCTPromiseRejectBlock)reject) { - [self runInBackground:^(){ - if (!fetch) { - // Do nothing, chunk is already preloaded - resolve(nil); - } else { + if (!fetch) { + // Do nothing, chunk is already preloaded + resolve(nil); + } else { + [self runInBackground:^(){ NSURL *chunkUrl = [NSURL URLWithString:chunkUrlString]; if ([[chunkUrl scheme] hasPrefix:@"http"]) { [self downloadAndCache:chunkId chunkUrl:chunkUrl completionHandler:^(NSError *error) { @@ -83,8 +83,8 @@ @implementation ChunkManager reject(UnsupportedScheme, [NSString stringWithFormat:@"Scheme in URL '%@' is not supported", chunkUrlString], nil); } - } - }]; + }]; + } } RCT_EXPORT_METHOD(invalidateChunks:(nonnull NSArray*)chunks