1

This is the context :

When I open my app I'm querying my firebase database. These queries are async, I'm waiting for firebase to give me the answer and then I return the value in redux. I'm using redux-persist so when redux get the response of firebase, redux-persist write the data on my phone.

This is the problem :

The problem is that if the user leave the app and then reopen it, if firebase return the response while the app is in background, redux-persist will try to write with AsynStorage. iOS doesn't allow this so my app will crash with these 2 errors

 Error storing data for key: "profile"

 'Failed to symbolicate warning, "%s":', 'Possible Unhandled Promise 
  Rejection (id: 0): 
  Failed to write manifest file.Error Domain=NSCocoaErrorDomain 
  Code=513 "You don’t have permission to save 
  the file “manifest.json” in the folder “RCTAsyncLocalStorage_V1”." 
  UserInfo=
  {NSFilePath=/var/mobile/Containers/Data/Application/
  C892F501-5057-4FE4-A622-2037C32D1373/Documents/
  RCTAsyncLocalStorage_V1/manifest.json, 
  NSUserStringVariant=Folder, NSUnderlyingError=0x17025b810 {Error 
  Domain=NSPOSIXErrorDomain Code=1 "Operation not permitted"}'

What I tried :

I have tested two solutions :

First Try I have tried to pause the persistor of redux-persist depending on the app state.

Store.js

export const persistor = persistStore(store, { storage: AsyncStorage }, () => {
    console.log('restored');
});

And then in my Home component

componentDidMount() {
    if (Platform.OS === 'ios') {
        AppState.addEventListener('change', this.handleAppStateChange);
}

handleAppStateChange = (appState) => {
    if (appState !== 'active') {
        persistor.pause();
    } else {
        persistor.resume()
    }
};

componentWillUnmount() {
    if (Platform.OS === 'ios') {
        AppState.removeEventListener('change', this.handleAppStateChange);
    }
}

Result Same Error as before, when I tried to console log the current state of the persistor he was paused and resumed on time.

Second Try I have tried to use a CustomAsyncStorage instead of AsyncStore in the persitStore(), I took all the code from AsyncStorage.js and then I add on every method a verification of the current app State who return the method if app state isn't active.

Result No luck redux-persist and redux stop working.

My Other ideas

  • Cancel every call of firebase when the app pass in background -> Can't be done no Method exist for that

  • In each method where I call Firebase and dispatching value in redux, check the current state of the app and return it only if app is active -> That means I should check every call so it's a lot of repetition.

React-native Version: 0.39.2

Redux-persist Version: 4.4.2

I'm open of any idea or any help for this case, what do you think I should do for resolve this issue? And which is the best

Thanks.

1 Answer 1

2

Check whether Data Protection is enabled in your iOS app's entitlements. It's probably configured to be NSFileProtectionComplete.

When data protection is enabled like this, all files are encrypted by default. This includes the storage backing React Native's AsyncStorage. This isn't a problem when the application is in the foreground, but, shortly after backgrounding the app or locking the device, iOS will throw away your decryption keys.

If your app attempts to write to a file (such as via AsyncStorage) after its decryption keys have been unloaded, the file operation will fail with precisely the (unhelpful) message that you saw:

Error Domain=NSCocoaErrorDomain Code=513 "You don’t have permission to save the file ...

An easy fix would be to change your default data protection level to be NSFileProtectionCompleteUntilFirstUserAuthentication. For more information, see "Encryption and Data Protection" in this guide: https://www.apple.com/business/docs/iOS_Security_Guide.pdf

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.