Skip to content

Commit

Permalink
[#27] iOS: Fixes "Background Downloads" feature + Updates related docs
Browse files Browse the repository at this point in the history
  • Loading branch information
birdofpreyru committed Jan 29, 2024
1 parent 2437f8e commit 8db8b52
Show file tree
Hide file tree
Showing 6 changed files with 120 additions and 18 deletions.
10 changes: 7 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -206,13 +206,17 @@ Background downloads in iOS require a bit of a setup.
First, in your `AppDelegate.m` file add the following:

```js
#import <RNFSManager.h>
#import <RNFSBackgroundDownloads.h>

...

- (void)application:(UIApplication *)application handleEventsForBackgroundURLSession:(NSString *)identifier completionHandler:(void (^)())completionHandler
- (void)application:(UIApplication *)application
handleEventsForBackgroundURLSession:(NSString *)identifier
completionHandler:(void (^)())completionHandler
{
[RNFSManager setCompletionHandlerForIdentifier:identifier completionHandler:completionHandler];
[RNFSBackgroundDownloads
setCompletionHandlerForIdentifier:identifier
completionHandler:completionHandler];
}

```
Expand Down
9 changes: 9 additions & 0 deletions example/ios/ReactNativeFsExample/AppDelegate.mm
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#import "AppDelegate.h"

#import <React/RCTBundleURLProvider.h>
#import <RNFSBackgroundDownloads.h>

@implementation AppDelegate

Expand All @@ -14,6 +15,14 @@ - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(
return [super application:application didFinishLaunchingWithOptions:launchOptions];
}

- (void)application:(UIApplication *)application
handleEventsForBackgroundURLSession:(NSString *)identifier
completionHandler:(void (^)())completionHandler
{
[RNFSBackgroundDownloads setCompletionHandlerForIdentifier:identifier
completionHandler:completionHandler];
}

- (NSURL *)sourceURLForBridge:(RCTBridge *)bridge
{
return [self getBundleURL];
Expand Down
53 changes: 52 additions & 1 deletion example/src/TestBaseMethods.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import { isEqual, isMatch } from 'lodash';
import React from 'react';
import { Platform, Text, View } from 'react-native';
import { AppState, Platform, Text, View } from 'react-native';

import {
appendFile,
completeHandlerIOS,
// copyAssetsFileIOS,
// copyAssetsVideoIOS,
// completeHandlerIOS,
Expand Down Expand Up @@ -326,6 +327,56 @@ const tests: { [name: string]: StatusOrEvaluator } = {
return 'fail';
}
},
// FOR THIS TEST TO RUN THE EXAMPLE APP SHOULD BE SENT TO THE BACKGROUND!
'[iOS] Background downloadFile()': async () => {
if (Platform.OS !== 'ios') return 'fail';

const url =
'https://raw.githubusercontent.com/birdofpreyru/react-native-fs/master/example/assets/test/good-utf8.txt';
const path = `${TemporaryDirectoryPath}/background-download-file-01`;
const good = 'GÖÖÐ\n';
try {
await unlink(path);
} catch {}
try {
console.info(
'Send the app to background to run the iOS background download test',
);
const promise = new Promise<'fail' | 'pass'>((resolve) => {
const sub = AppState.addEventListener('change', async (state) => {
if (state === 'background') {
const { jobId, promise: downloadPromise } = downloadFile({
fromUrl: url,
toFile: path,
});
sub.remove();
const res = await downloadPromise;
completeHandlerIOS(jobId);
if (
typeof jobId !== 'number' ||
res.bytesWritten !== 8 ||
res.statusCode !== 200
) {
console.info('Background download test failed');
resolve('fail');
return;
}
const file = await readFile(path);
if (file !== good) {
console.info('Background download test failed');
resolve('fail');
return;
}
console.info('Background download test passed');
resolve('pass');
}
});
});
return promise;
} catch {
return 'fail';
}
},
'exists()': async () => {
const path = `${TemporaryDirectoryPath}/test-exists-file`;
try {
Expand Down
21 changes: 21 additions & 0 deletions ios/RNFSBackgroundDownloads.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
//
// RNFSBackgroundDownloads.h
// Pods
//
// Created by Sergey Pogodin on 29/1/24.
//

#ifndef RNFSBackgroundDownloads_h
#define RNFSBackgroundDownloads_h

typedef void (^CompletionHandler)(void);

@interface RNFSBackgroundDownloads: NSObject

+ (void) complete:(NSString*)uuid;

+ (void) setCompletionHandlerForIdentifier:(NSString*)identifier
completionHandler:(CompletionHandler)completionHandler;
@end

#endif /* RNFSBackgroundDownloads_h */
29 changes: 29 additions & 0 deletions ios/RNFSBackgroundDownloads.mm
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
//
// RNFSBackgroundDownloads.m
// dr-pogodin-react-native-fs
//
// Created by Sergey Pogodin on 29/1/24.
//

#import "RNFSBackgroundDownloads.h"

@implementation RNFSBackgroundDownloads;

static NSMutableDictionary *completionHandlers;

+ (void)complete:(NSString *)uuid
{
CompletionHandler completionHandler = [completionHandlers objectForKey:uuid];
if (completionHandler) {
completionHandler();
[completionHandlers removeObjectForKey:uuid];
}
}

+ (void)setCompletionHandlerForIdentifier:(NSString *)identifier completionHandler:(__strong CompletionHandler)completionHandler
{
if (!completionHandlers) completionHandlers = [[NSMutableDictionary alloc] init];
[completionHandlers setValue:completionHandler forKey:identifier];
}

@end;
16 changes: 2 additions & 14 deletions ios/ReactNativeFs.mm
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,9 @@
#import <CommonCrypto/CommonDigest.h>
#import <Photos/Photos.h>

#import "RNFSBackgroundDownloads.h"
#import "RNFSException.h"

typedef void (^CompletionHandler)(void);

@implementation ReactNativeFs

// The prefix of "Bookmark URLs".
Expand All @@ -32,7 +31,6 @@ @implementation ReactNativeFs
// and pass the resulting "Bookmark URLs" string around.
static NSString *BOOKMARK = @"bookmark://";

static NSMutableDictionary *completionHandlers;
NSMutableDictionary<NSValue*,NSArray*> *pendingPickFilePromises;

RCT_EXPORT_MODULE()
Expand Down Expand Up @@ -671,11 +669,7 @@ - (instancetype) init
if (self.uuids) {
NSNumber *jid = [NSNumber numberWithDouble:jobId];
NSString *uuid = [self.uuids objectForKey:[jid stringValue]];
CompletionHandler completionHandler = [completionHandlers objectForKey:uuid];
if (completionHandler) {
completionHandler();
[completionHandlers removeObjectForKey:uuid];
}
[RNFSBackgroundDownloads complete:uuid];
}
}

Expand Down Expand Up @@ -1250,12 +1244,6 @@ + (NSURL*) pathToUrl:(NSString*)path error:(NSError**)error
return res;
}

+(void)setCompletionHandlerForIdentifier: (NSString *)identifier completionHandler: (CompletionHandler)completionHandler
{
if (!completionHandlers) completionHandlers = [[NSMutableDictionary alloc] init];
[completionHandlers setValue:completionHandler forKey:identifier];
}

- (dispatch_queue_t)methodQueue
{
return dispatch_queue_create("pe.lum.newrnfs", DISPATCH_QUEUE_SERIAL);
Expand Down

0 comments on commit 8db8b52

Please sign in to comment.