Skip to content

Commit 36e9a12

Browse files
alehtido64
authored andcommitted
fix(iOS): Don't reset the storage when the manifest file cannot be read because of iOS data protection (#270)
This is to distinguish "manifest file does not exist or is corrupted" and "have no access to the manifest file yet" cases. Starting with an empty dictionary is a reasonable fallback in case the manifest does not exist or cannot be parsed because of being corrupted or incompatible. However doing so might lead to unnecessary data loss when the app simply has no access to its documents yet due to iOS data protection (if enabled and when the app launches while the device is locked due to e.g. geofencing, silent notification, external accessory, etc).
1 parent 9aad474 commit 36e9a12

File tree

1 file changed

+22
-5
lines changed

1 file changed

+22
-5
lines changed

ios/RNCAsyncStorage.m

Lines changed: 22 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -343,16 +343,33 @@ - (NSDictionary *)_ensureSetup
343343
}
344344
RCTHasCreatedStorageDirectory = YES;
345345
}
346+
346347
if (!_haveSetup) {
347-
NSDictionary *errorOut;
348+
NSDictionary *errorOut = nil;
348349
NSString *serialized = RCTReadFile(RCTGetManifestFilePath(), RCTManifestFileName, &errorOut);
349-
_manifest = serialized ? RCTJSONParseMutable(serialized, &error) : [NSMutableDictionary new];
350-
if (error) {
351-
RCTLogWarn(@"Failed to parse manifest - creating new one.\n\n%@", error);
352-
_manifest = [NSMutableDictionary new];
350+
if (!serialized) {
351+
if (errorOut) {
352+
// We cannot simply create a new manifest in case the file does exist but we have no access to it.
353+
// This can happen when data protection is enabled for the app and we are trying to read the manifest
354+
// while the device is locked. (The app can be started by the system even if the device is locked due to
355+
// e.g. a geofence event.)
356+
RCTLogError(@"Could not open the existing manifest, perhaps data protection is enabled?\n\n%@", errorOut);
357+
return errorOut;
358+
} else {
359+
// We can get nil without errors only when the file does not exist.
360+
RCTLogTrace(@"Manifest does not exist - creating a new one.\n\n%@", errorOut);
361+
_manifest = [NSMutableDictionary new];
362+
}
363+
} else {
364+
_manifest = RCTJSONParseMutable(serialized, &error);
365+
if (!_manifest) {
366+
RCTLogError(@"Failed to parse manifest - creating a new one.\n\n%@", error);
367+
_manifest = [NSMutableDictionary new];
368+
}
353369
}
354370
_haveSetup = YES;
355371
}
372+
356373
return nil;
357374
}
358375

0 commit comments

Comments
 (0)