Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[iOS] AsyncStorage data persists after uninstalling and re-installing app #342

Closed
bachhuberdesign opened this issue Apr 23, 2020 · 27 comments · Fixed by #455
Closed

[iOS] AsyncStorage data persists after uninstalling and re-installing app #342

bachhuberdesign opened this issue Apr 23, 2020 · 27 comments · Fixed by #455
Labels
enhancement New feature or request platform: iOS This is iOS specific platform: macOS This is macOS specific

Comments

@bachhuberdesign
Copy link

bachhuberdesign commented Apr 23, 2020

Current behavior

Using the latest stable release (1.9.0), AsyncStorage items that are set persist after an iOS app is uninstalled and then re-installed.

Expected behavior

AsyncStorage should be completely clear after uninstalling/reinstalling an app. This is how the framework bundled AsyncStorage behaves, so one would expect the community version to function the same way. If this persistence is intentional, it should be documented (as far as I can tell there is nothing in the docs that would explain this behavior, but I might have missed something). Apologies if I am mistaken or if this issue has been reported already.

Repro steps

  1. AsyncStorage.setItem('someKey', 'someData');
  2. Uninstall iOS app
  3. Re-install iOS app
  4. const data = AsyncStorage.getItem('someKey'); // returns someData

Environment

  • Async Storage version: 1.9.0
  • React-Native version: 0.62.2
  • Platform tested: iOS 13.3
@krizzu
Copy link
Member

krizzu commented Apr 24, 2020

Interesting. I did just a quick check (init new app, add AsyncStorage, save data, removed app, installed again, read data) and the data is indeed removed.
Are you using real device or simulator?

@madman61rus
Copy link

madman61rus commented May 8, 2020

I have the same problem on IOS simulator when i'm using React Native Debugger. If i disable debug mode, all is fine.

@bachhuberdesign
Copy link
Author

bachhuberdesign commented May 8, 2020

My issue was on simulator as well (XCode 11.3)

@kennyho-ml
Copy link

I have this problem using expo 37 + react native 61.4.

@krizzu
Copy link
Member

krizzu commented Jun 17, 2020

Can anyone provide a project where issue is reproducible ?

@JacquesLeupin
Copy link

I've run into this as well on a physical iOS device, using:

"@react-native-community/async-storage": "^1.11.0",
"react-native": "0.62.2",

Project repo is private, but I can provide more details upon request. App name is Serenity: Guided Mental Health.

@krizzu
Copy link
Member

krizzu commented Jul 11, 2020

@JacquesLeupin Please do include some repro steps, thanks!

@developius
Copy link

How can we maintain this behaviour? I have a scenario where it's imperative that the data in AsyncStorage can be persisted across uninstalls/reinstalls. This is because a unique device ID is stored within it.
I read that iCloud will backup the data and can recover it when reinstalled, and the same for Android with the Play Store. Is that true?

@exotexot
Copy link

@developius maybe storing your device id in keychain solve your problem.

I also think that clearing data after app uninstall is important to avoid accumulation of garbage...

@nishanttatva
Copy link

@JacquesLeupin were you able to fix this?

@JacquesLeupin
Copy link

@nishanttatva nope, i never found a fix for this issue.

our app uses firebase for auth, and we refactored to avoid storing most data in AsyncStorage. to automatically log out a user, we implemented this workaround.

@developius
Copy link

@exotexot good call, thanks!

@krizzu
Copy link
Member

krizzu commented Aug 28, 2020

Since we're storing data in Application Support directory, it's backed up by default.

We need a way to opt out from doing that. Going to work on that in upcoming days

@nishanttatva
Copy link

@krizzu

We need a way to opt out from doing that. Going to work on that in upcoming days

Were you able to find anything?

@fbartho
Copy link

fbartho commented Oct 7, 2020

We also need this fix as it causes problems when users try to uninstall/reinstall (particularly noticeable when trying to experience a First-App-Launch experience)! This is a pretty urgent issue for our Application, so I'd love to help.

There's a filesystem flag that can be set on files to enable/disable this type of behavior on iOS.

@krizzu do you need any help getting a solution for this?

From an API perspective @krizzu, what did you want for this? Solutions that come to mind:
A. a standalone global flag that users could attach to RN.AsyncStorage -- RN.AsyncStorage.setBackupMode("no-restore")

  • users could setItem with a magic key: __ASYNC_STORAGE_BACKUP_MODE__ = "no-restore"
  • Change this from a Singleton-type API where there's only 1 Storage "Domain" to multiple storage domains + add an API to configure behavior for each domain. -- This would be multiple files on disk, and users would need an API to get "other" storage domains. -- This would be the biggest API enhancement, but it could be backwards compatible…

@krizzu
Copy link
Member

krizzu commented Oct 8, 2020

@fbartho

I've created an initial PR that has backup feature toggling. I cannot repro this myself, so it'd be great if you (or anyone else) could give it a try.

Regarding using that feature - I thought about adding an entry to package.json like AsyncStorage where we'd keep all the feature flags (for Android too). We'd have to find a way to read it on AppLaunch (where AsyncStorage init is happening).

@tido64 tido64 linked a pull request Oct 14, 2020 that will close this issue
@tido64 tido64 added enhancement New feature or request platform: iOS This is iOS specific platform: macOS This is macOS specific labels Oct 14, 2020
@fbartho
Copy link

fbartho commented Oct 14, 2020

@krizzu we'd be happy to try a beta build that has the final implementation of your proposed feature -- I've commented on your PR for now with some further thoughts. This is affecting our app in production, so we're comfortable testing an appropriate beta build in our normal QA process.

@hannahcx
Copy link

Hello what is the status of this? It is interesting one IOS app is storing values correctly, and store is not persisted on reinstall. Another app the values are persisted on reinstall, so I'm wondering is it due to the fact "On iOS, AsyncStorage is backed by native code that stores small values in a serialized dictionary and larger values in separate files." That maybe this second app has larger values and is getting stored in a different place in the system? We are running into issues with this so I'm wondering the status.

@johnjoshuadablo
Copy link

Any status on this?

@topwebtek7
Copy link

Any workaround to this issue?

@falcoagustin
Copy link

falcoagustin commented Mar 20, 2022

Also interested about this fix. @krizzu why is this closed?

@endronk
Copy link

endronk commented Apr 1, 2022

From what I read on @krizzu 's PR here, it should already be excluded from iCloud backup. Also here.
I also cannot check myself, but some of our users still experience this data persistence.

@endronk
Copy link

endronk commented Apr 1, 2022

Ahh, my bad. We use expo-secure-store on some of our data, and they go into backup.

Please note that for iOS standalone apps, data stored with expo-secure-store can persist across app installs.

@SophieJung7
Copy link

Any update on this PR?

@alexjegor
Copy link

alexjegor commented Sep 19, 2023

You can add following lines into your AppDelegate.mm file to clear Application Support directory on first launch:

- (void)clearApplicationCacheOnFirstAppRun {
  NSString *storageKey = @"kIsNotTheFirstAppRun";
  BOOL isFirstAppRun = ![[NSUserDefaults standardUserDefaults] boolForKey: storageKey];
  if (isFirstAppRun) {
    [self clearKeychainOnFirstAppRun];
    // [self clearApplicationSupportDirectory];
  }
  [[NSUserDefaults standardUserDefaults] setBool: true forKey: storageKey];
}

// - (void)clearKeychainOnFirstAppRun {
//   NSArray *secItemClasses = @[(__bridge id)kSecClassGenericPassword,
//                               (__bridge id)kSecClassInternetPassword,
//                               (__bridge id)kSecClassCertificate,
//                               (__bridge id)kSecClassKey,
//                               (__bridge id)kSecClassIdentity];
//   for (id secItemClass in secItemClasses) {
//     NSDictionary *spec = @{(__bridge id)kSecClass: secItemClass};
//     SecItemDelete((__bridge CFDictionaryRef)spec);
//   }
// }

- (void)clearApplicationSupportDirectory {
  NSFileManager *fileManager = [NSFileManager defaultManager];

  NSError *error;
  NSString *applicationSupportPath = [[fileManager
                                    URLForDirectory:NSApplicationSupportDirectory
                                           inDomain:NSUserDomainMask
                                  appropriateForURL:nil
                                             create:YES
                                              error:&error] path];
  
  NSArray *items = [fileManager contentsOfDirectoryAtPath:applicationSupportPath error:&error];
  
  if (error) {
    NSLog(@"Error reading contents of app support directory: %@", error);
    return;
  }

  for (NSString *item in items) {
    NSString *itemPath = [applicationSupportPath stringByAppendingPathComponent:item];
    [fileManager removeItemAtPath:itemPath error:&error];

    if (error) {
      NSLog(@"Error removing item: %@, error: %@", item, error);
    }
  }
}

Uncomment clearKeychainOnFirstAppRun method if you're using react-native-encrypted-storage, which seems to have similar issue.

Oh, and don't forget to call it inside didFinishLaunchingWithOptions function.

@gunwooa
Copy link

gunwooa commented Dec 4, 2023

Ahh, my bad. We use expo-secure-store on some of our data, and they go into backup.

Please note that for iOS standalone apps, data stored with expo-secure-store can persist across app installs.

Thanks to you, I found the cause of the problem.
When we checked our code again, we found that we were using expo-secure-store, not react-native-async-storag.
After changing expo-secure-store to react-native-async-storag, it is no longer stored in iCloud!!

@feri-irawan
Copy link

Same problem, but in Android <= 10, the data still there after uninstall and reinstall the app.
I am using zustand + AsyncStorage for auth session

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request platform: iOS This is iOS specific platform: macOS This is macOS specific
Projects
None yet
Development

Successfully merging a pull request may close this issue.