diff --git a/ios/RNCAsyncStorage.m b/ios/RNCAsyncStorage.m index 18556296..bd9926fa 100644 --- a/ios/RNCAsyncStorage.m +++ b/ios/RNCAsyncStorage.m @@ -343,16 +343,33 @@ - (NSDictionary *)_ensureSetup } RCTHasCreatedStorageDirectory = YES; } + if (!_haveSetup) { - NSDictionary *errorOut; + NSDictionary *errorOut = nil; NSString *serialized = RCTReadFile(RCTGetManifestFilePath(), RCTManifestFileName, &errorOut); - _manifest = serialized ? RCTJSONParseMutable(serialized, &error) : [NSMutableDictionary new]; - if (error) { - RCTLogWarn(@"Failed to parse manifest - creating new one.\n\n%@", error); - _manifest = [NSMutableDictionary new]; + if (!serialized) { + if (errorOut) { + // We cannot simply create a new manifest in case the file does exist but we have no access to it. + // This can happen when data protection is enabled for the app and we are trying to read the manifest + // while the device is locked. (The app can be started by the system even if the device is locked due to + // e.g. a geofence event.) + RCTLogError(@"Could not open the existing manifest, perhaps data protection is enabled?\n\n%@", errorOut); + return errorOut; + } else { + // We can get nil without errors only when the file does not exist. + RCTLogTrace(@"Manifest does not exist - creating a new one.\n\n%@", errorOut); + _manifest = [NSMutableDictionary new]; + } + } else { + _manifest = RCTJSONParseMutable(serialized, &error); + if (!_manifest) { + RCTLogError(@"Failed to parse manifest - creating a new one.\n\n%@", error); + _manifest = [NSMutableDictionary new]; + } } _haveSetup = YES; } + return nil; }