Migrate to shared data NSUserDefaults.

This commit is contained in:
Matthew Chen 2017-11-28 13:46:26 -05:00
parent cd11ec5698
commit edaf65223a
13 changed files with 206 additions and 102 deletions

View File

@ -24,6 +24,7 @@
#import "VersionMigrations.h" #import "VersionMigrations.h"
#import "ViewControllerUtils.h" #import "ViewControllerUtils.h"
#import <AxolotlKit/SessionCipher.h> #import <AxolotlKit/SessionCipher.h>
#import <SignalServiceKit/NSUserDefaults+OWS.h>
#import <SignalServiceKit/OWSBatchMessageProcessor.h> #import <SignalServiceKit/OWSBatchMessageProcessor.h>
#import <SignalServiceKit/OWSDisappearingMessagesJob.h> #import <SignalServiceKit/OWSDisappearingMessagesJob.h>
#import <SignalServiceKit/OWSFailedAttachmentDownloadsJob.h> #import <SignalServiceKit/OWSFailedAttachmentDownloadsJob.h>
@ -103,6 +104,18 @@ static NSString *const kURLHostVerifyPrefix = @"verify";
DDLogWarn(@"%@ application: didFinishLaunchingWithOptions.", self.logTag); DDLogWarn(@"%@ application: didFinishLaunchingWithOptions.", self.logTag);
// We need to this _after_ we set up logging but _before_ we do
// anything else.
[self ensureMigrationToSharedData];
#if RELEASE
// ensureMigrationToSharedData may have changed the state of the logging
// preference, so honor that change if necessary.
if (loggingIsEnabled && !OWSPreferences.loggingIsEnabled) {
[DebugLogger.sharedLogger disableFileLogging];
}
#endif
[AppVersion instance]; [AppVersion instance];
[self startupLogging]; [self startupLogging];
@ -176,6 +189,21 @@ static NSString *const kURLHostVerifyPrefix = @"verify";
return YES; return YES;
} }
- (void)ensureMigrationToSharedData
{
if ([OWSPreferences hasMigratedToSharedData]) {
return;
}
[NSUserDefaults migrateToSharedUserDefaults];
[TSStorageManager migrateToSharedData];
[OWSProfileManager migrateToSharedData];
[TSAttachmentStream migrateToSharedData];
[OWSPreferences setHasMigratedToSharedData:YES];
}
- (void)startupLogging - (void)startupLogging
{ {
DDLogInfo(@"iOS Version: %@", [UIDevice currentDevice].systemVersion); DDLogInfo(@"iOS Version: %@", [UIDevice currentDevice].systemVersion);

View File

@ -29,6 +29,8 @@ extern const NSUInteger kOWSProfileManager_MaxAvatarDiameter;
- (void)resetProfileStorage; - (void)resetProfileStorage;
+ (void)migrateToSharedData;
#pragma mark - Local Profile #pragma mark - Local Profile
// These two methods should only be called from the main thread. // These two methods should only be called from the main thread.

View File

@ -1384,22 +1384,29 @@ const NSUInteger kOWSProfileManager_MaxAvatarDiameter = 640;
return image; return image;
} }
+ (NSString *)oldProfileAvatarsDirPath
{
return [[OWSFileSystem appDocumentDirectoryPath] stringByAppendingPathComponent:@"ProfileAvatars"];
}
+ (NSString *)newProfileAvatarsDirPath
{
return [[OWSFileSystem appSharedDataDirectoryPath] stringByAppendingPathComponent:@"ProfileAvatars"];
}
+ (void)migrateToSharedData
{
[OWSFileSystem moveAppFilePath:self.oldProfileAvatarsDirPath
sharedDataFilePath:self.newProfileAvatarsDirPath
exceptionName:@"ProfileManagerCouldNotMigrateProfileDirectory"];
}
- (NSString *)profileAvatarsDirPath - (NSString *)profileAvatarsDirPath
{ {
static NSString *profileAvatarsDirPath = nil; static NSString *profileAvatarsDirPath = nil;
static dispatch_once_t onceToken; static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{ dispatch_once(&onceToken, ^{
NSString *documentDirPath = [OWSFileSystem appDocumentDirectoryPath]; profileAvatarsDirPath = OWSProfileManager.newProfileAvatarsDirPath;
NSString *sharedDataDirPath = [OWSFileSystem appSharedDataDirectoryPath];
NSString *oldProfileAvatarsDirPath = [documentDirPath stringByAppendingPathComponent:@"ProfileAvatars"];
NSString *newProfileAvatarsDirPath = [sharedDataDirPath stringByAppendingPathComponent:@"ProfileAvatars"];
[OWSFileSystem moveAppFilePath:oldProfileAvatarsDirPath
sharedDataFilePath:newProfileAvatarsDirPath
exceptionName:@"ProfileManagerCouldNotMigrateProfileDirectory"];
profileAvatarsDirPath = newProfileAvatarsDirPath;
BOOL isDirectory; BOOL isDirectory;
BOOL exists = [[NSFileManager defaultManager] fileExistsAtPath:profileAvatarsDirPath isDirectory:&isDirectory]; BOOL exists = [[NSFileManager defaultManager] fileExistsAtPath:profileAvatarsDirPath isDirectory:&isDirectory];

View File

@ -27,6 +27,9 @@ extern NSString *const OWSPreferencesKeyEnableDebugLog;
#pragma mark - Specific Preferences #pragma mark - Specific Preferences
+ (BOOL)hasMigratedToSharedData;
+ (void)setHasMigratedToSharedData:(BOOL)value;
- (BOOL)getHasSentAMessage; - (BOOL)getHasSentAMessage;
- (void)setHasSentAMessage:(BOOL)enabled; - (void)setHasSentAMessage:(BOOL)enabled;

View File

@ -4,6 +4,7 @@
#import "OWSPreferences.h" #import "OWSPreferences.h"
#import "TSStorageHeaders.h" #import "TSStorageHeaders.h"
#import <SignalServiceKit/NSUserDefaults+OWS.h>
NS_ASSUME_NONNULL_BEGIN NS_ASSUME_NONNULL_BEGIN
@ -22,6 +23,7 @@ NSString *const OWSPreferencesKeyCallKitPrivacyEnabled = @"CallKitPrivacyEnabled
NSString *const OWSPreferencesKeyCallsHideIPAddress = @"CallsHideIPAddress"; NSString *const OWSPreferencesKeyCallsHideIPAddress = @"CallsHideIPAddress";
NSString *const OWSPreferencesKeyHasDeclinedNoContactsView = @"hasDeclinedNoContactsView"; NSString *const OWSPreferencesKeyHasDeclinedNoContactsView = @"hasDeclinedNoContactsView";
NSString *const OWSPreferencesKeyIOSUpgradeNagVersion = @"iOSUpgradeNagVersion"; NSString *const OWSPreferencesKeyIOSUpgradeNagVersion = @"iOSUpgradeNagVersion";
NSString *const OWSPreferencesKey_HasMigratedToSharedData = @"hasMigratedToSharedData";
@implementation OWSPreferences @implementation OWSPreferences
@ -40,10 +42,7 @@ NSString *const OWSPreferencesKeyIOSUpgradeNagVersion = @"iOSUpgradeNagVersion";
#pragma mark - Helpers #pragma mark - Helpers
- (void)clear { - (void)clear {
@synchronized(self) { [NSUserDefaults removeAll];
NSString *appDomain = NSBundle.mainBundle.bundleIdentifier;
[NSUserDefaults.standardUserDefaults removePersistentDomainForName:appDomain];
}
} }
- (nullable id)tryGetValueForKey:(NSString *)key - (nullable id)tryGetValueForKey:(NSString *)key
@ -61,6 +60,23 @@ NSString *const OWSPreferencesKeyIOSUpgradeNagVersion = @"iOSUpgradeNagVersion";
#pragma mark - Specific Preferences #pragma mark - Specific Preferences
+ (BOOL)hasMigratedToSharedData
{
NSNumber *preference = [NSUserDefaults.appUserDefaults objectForKey:OWSPreferencesKey_HasMigratedToSharedData];
if (preference) {
return [preference boolValue];
} else {
return NO;
}
}
+ (void)setHasMigratedToSharedData:(BOOL)value
{
[NSUserDefaults.appUserDefaults setObject:@(value) forKey:OWSPreferencesKey_HasMigratedToSharedData];
[NSUserDefaults.appUserDefaults synchronize];
}
- (BOOL)screenSecurityIsEnabled - (BOOL)screenSecurityIsEnabled
{ {
NSNumber *preference = [self tryGetValueForKey:OWSPreferencesKeyScreenSecurity]; NSNumber *preference = [self tryGetValueForKey:OWSPreferencesKeyScreenSecurity];
@ -94,7 +110,7 @@ NSString *const OWSPreferencesKeyIOSUpgradeNagVersion = @"iOSUpgradeNagVersion";
+ (BOOL)loggingIsEnabled + (BOOL)loggingIsEnabled
{ {
NSNumber *preference = [NSUserDefaults.standardUserDefaults objectForKey:OWSPreferencesKeyEnableDebugLog]; NSNumber *preference = [NSUserDefaults.appUserDefaults objectForKey:OWSPreferencesKeyEnableDebugLog];
if (preference) { if (preference) {
return [preference boolValue]; return [preference boolValue];
@ -108,8 +124,8 @@ NSString *const OWSPreferencesKeyIOSUpgradeNagVersion = @"iOSUpgradeNagVersion";
// Logging preferences are stored in UserDefaults instead of the database, so that we can (optionally) start // Logging preferences are stored in UserDefaults instead of the database, so that we can (optionally) start
// logging before the database is initialized. This is important because sometimes there are problems *with* the // logging before the database is initialized. This is important because sometimes there are problems *with* the
// database initialization, and without logging it would be hard to track down. // database initialization, and without logging it would be hard to track down.
[NSUserDefaults.standardUserDefaults setObject:@(flag) forKey:OWSPreferencesKeyEnableDebugLog]; [NSUserDefaults.appUserDefaults setObject:@(flag) forKey:OWSPreferencesKeyEnableDebugLog];
[NSUserDefaults.standardUserDefaults synchronize]; [NSUserDefaults.appUserDefaults synchronize];
} }
- (void)setHasSentAMessage:(BOOL)enabled - (void)setHasSentAMessage:(BOOL)enabled

View File

@ -8,9 +8,10 @@
#import "OWSDatabaseMigrationRunner.h" #import "OWSDatabaseMigrationRunner.h"
#import "PushManager.h" #import "PushManager.h"
#import "SignalKeyingStorage.h" #import "SignalKeyingStorage.h"
#import "TSAccountManager.h"
#import "TSNetworkManager.h"
#import <SignalServiceKit/AppVersion.h> #import <SignalServiceKit/AppVersion.h>
#import <SignalServiceKit/NSUserDefaults+OWS.h>
#import <SignalServiceKit/TSAccountManager.h>
#import <SignalServiceKit/TSNetworkManager.h>
#define NEEDS_TO_REGISTER_PUSH_KEY @"Register For Push" #define NEEDS_TO_REGISTER_PUSH_KEY @"Register For Push"
#define NEEDS_TO_REGISTER_ATTRIBUTES @"Register Attributes" #define NEEDS_TO_REGISTER_ATTRIBUTES @"Register Attributes"
@ -125,39 +126,39 @@
+ (void)blockingAttributesUpdate { + (void)blockingAttributesUpdate {
LIControllerBlockingOperation blockingOperation = ^BOOL(void) { LIControllerBlockingOperation blockingOperation = ^BOOL(void) {
[[NSUserDefaults standardUserDefaults] setObject:@YES forKey:NEEDS_TO_REGISTER_ATTRIBUTES]; [[NSUserDefaults appUserDefaults] setObject:@YES forKey:NEEDS_TO_REGISTER_ATTRIBUTES];
__block dispatch_semaphore_t sema = dispatch_semaphore_create(0); __block dispatch_semaphore_t sema = dispatch_semaphore_create(0);
__block BOOL success; __block BOOL success;
TSUpdateAttributesRequest *request = [[TSUpdateAttributesRequest alloc] initWithManualMessageFetching:NO]; TSUpdateAttributesRequest *request = [[TSUpdateAttributesRequest alloc] initWithManualMessageFetching:NO];
[[TSNetworkManager sharedManager] makeRequest:request [[TSNetworkManager sharedManager] makeRequest:request
success:^(NSURLSessionDataTask *task, id responseObject) { success:^(NSURLSessionDataTask *task, id responseObject) {
success = YES; success = YES;
dispatch_semaphore_signal(sema); dispatch_semaphore_signal(sema);
} }
failure:^(NSURLSessionDataTask *task, NSError *error) { failure:^(NSURLSessionDataTask *task, NSError *error) {
if (!IsNSErrorNetworkFailure(error)) { if (!IsNSErrorNetworkFailure(error)) {
OWSProdError([OWSAnalyticsEvents errorUpdateAttributesRequestFailed]); OWSProdError([OWSAnalyticsEvents errorUpdateAttributesRequestFailed]);
} }
success = NO; success = NO;
DDLogError(@"Updating attributess failed with error: %@", error.description); DDLogError(@"Updating attributess failed with error: %@", error.description);
dispatch_semaphore_signal(sema); dispatch_semaphore_signal(sema);
}]; }];
dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER); dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER);
return success; return success;
}; };
LIControllerRetryBlock retryBlock = [LockInteractionController defaultNetworkRetry]; LIControllerRetryBlock retryBlock = [LockInteractionController defaultNetworkRetry];
[LockInteractionController performBlock:blockingOperation [LockInteractionController performBlock:blockingOperation
completionBlock:^{ completionBlock:^{
[[NSUserDefaults standardUserDefaults] removeObjectForKey:NEEDS_TO_REGISTER_ATTRIBUTES]; [[NSUserDefaults appUserDefaults] removeObjectForKey:NEEDS_TO_REGISTER_ATTRIBUTES];
DDLogWarn(@"Successfully updated attributes."); DDLogWarn(@"Successfully updated attributes.");
} }
retryBlock:retryBlock retryBlock:retryBlock
usesNetwork:YES]; usesNetwork:YES];

View File

@ -57,6 +57,8 @@ NS_ASSUME_NONNULL_BEGIN
- (CGFloat)audioDurationSeconds; - (CGFloat)audioDurationSeconds;
+ (void)migrateToSharedData;
@end @end
NS_ASSUME_NONNULL_END NS_ASSUME_NONNULL_END

View File

@ -180,22 +180,29 @@ NS_ASSUME_NONNULL_BEGIN
return [dataSource writeToPath:filePath]; return [dataSource writeToPath:filePath];
} }
+ (NSString *)oldAttachmentsDirPath
{
return [[OWSFileSystem appDocumentDirectoryPath] stringByAppendingPathComponent:@"Attachments"];
}
+ (NSString *)newAttachmentsDirPath
{
return [[OWSFileSystem appSharedDataDirectoryPath] stringByAppendingPathComponent:@"Attachments"];
}
+ (void)migrateToSharedData
{
[OWSFileSystem moveAppFilePath:self.oldAttachmentsDirPath
sharedDataFilePath:self.newAttachmentsDirPath
exceptionName:@"CouldNotMigrateAttachmentsDirectory"];
}
+ (NSString *)attachmentsFolder + (NSString *)attachmentsFolder
{ {
static NSString *attachmentsFolder = nil; static NSString *attachmentsFolder = nil;
static dispatch_once_t onceToken; static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{ dispatch_once(&onceToken, ^{
NSString *documentDirPath = [OWSFileSystem appDocumentDirectoryPath]; attachmentsFolder = TSAttachmentStream.newAttachmentsDirPath;
NSString *sharedDataDirPath = [OWSFileSystem appSharedDataDirectoryPath];
NSString *oldAttachmentsDirPath = [documentDirPath stringByAppendingPathComponent:@"Attachments"];
NSString *newAttachmentsDirPath = [sharedDataDirPath stringByAppendingPathComponent:@"Attachments"];
[OWSFileSystem moveAppFilePath:oldAttachmentsDirPath
sharedDataFilePath:newAttachmentsDirPath
exceptionName:@"CouldNotMigrateAttachmentsDirectory"];
attachmentsFolder = newAttachmentsDirPath;
BOOL isDirectory; BOOL isDirectory;
BOOL exists = [[NSFileManager defaultManager] fileExistsAtPath:attachmentsFolder isDirectory:&isDirectory]; BOOL exists = [[NSFileManager defaultManager] fileExistsAtPath:attachmentsFolder isDirectory:&isDirectory];

View File

@ -63,6 +63,8 @@ NS_ASSUME_NONNULL_BEGIN
@property (nullable, nonatomic, readonly) YapDatabaseConnection *dbReadConnection; @property (nullable, nonatomic, readonly) YapDatabaseConnection *dbReadConnection;
@property (nullable, nonatomic, readonly) YapDatabaseConnection *dbReadWriteConnection; @property (nullable, nonatomic, readonly) YapDatabaseConnection *dbReadWriteConnection;
+ (void)migrateToSharedData;
@end @end
NS_ASSUME_NONNULL_END NS_ASSUME_NONNULL_END

View File

@ -207,10 +207,11 @@ void setDatabaseInitialized()
static TSStorageManager *sharedManager = nil; static TSStorageManager *sharedManager = nil;
static dispatch_once_t onceToken; static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{ dispatch_once(&onceToken, ^{
sharedManager = [[self alloc] initDefault];
#if TARGET_OS_IPHONE #if TARGET_OS_IPHONE
[sharedManager protectSignalFiles]; [TSStorageManager protectSignalFiles];
#endif #endif
sharedManager = [[self alloc] initDefault];
}); });
return sharedManager; return sharedManager;
} }
@ -355,7 +356,8 @@ void setDatabaseInitialized()
[TSDatabaseView asyncRegistrationCompletion]; [TSDatabaseView asyncRegistrationCompletion];
} }
- (void)protectSignalFiles { + (void)protectSignalFiles
{
// The old database location was in the Document directory, // The old database location was in the Document directory,
// so protect the database files individually. // so protect the database files individually.
[OWSFileSystem protectFolderAtPath:[self oldDatabaseFilePath]]; [OWSFileSystem protectFolderAtPath:[self oldDatabaseFilePath]];
@ -375,12 +377,12 @@ void setDatabaseInitialized()
return FALSE; return FALSE;
} }
- (NSString *)oldDatabaseDirPath + (NSString *)oldDatabaseDirPath
{ {
return [OWSFileSystem appDocumentDirectoryPath]; return [OWSFileSystem appDocumentDirectoryPath];
} }
- (NSString *)newDatabaseDirPath + (NSString *)newDatabaseDirPath
{ {
NSString *databaseDirPath = [[OWSFileSystem appSharedDataDirectoryPath] stringByAppendingPathComponent:@"database"]; NSString *databaseDirPath = [[OWSFileSystem appSharedDataDirectoryPath] stringByAppendingPathComponent:@"database"];
@ -405,52 +407,52 @@ void setDatabaseInitialized()
return databaseDirPath; return databaseDirPath;
} }
- (NSString *)databaseFilename + (NSString *)databaseFilename
{ {
return @"Signal.sqlite"; return @"Signal.sqlite";
} }
- (NSString *)databaseFilename_SHM + (NSString *)databaseFilename_SHM
{ {
return [self.databaseFilename stringByAppendingString:@"-shm"]; return [self.databaseFilename stringByAppendingString:@"-shm"];
} }
- (NSString *)databaseFilename_WAL + (NSString *)databaseFilename_WAL
{ {
return [self.databaseFilename stringByAppendingString:@"-wal"]; return [self.databaseFilename stringByAppendingString:@"-wal"];
} }
- (NSString *)oldDatabaseFilePath + (NSString *)oldDatabaseFilePath
{ {
return [self.oldDatabaseDirPath stringByAppendingPathComponent:self.databaseFilename]; return [self.oldDatabaseDirPath stringByAppendingPathComponent:self.databaseFilename];
} }
- (NSString *)oldDatabaseFilePath_SHM + (NSString *)oldDatabaseFilePath_SHM
{ {
return [self.oldDatabaseDirPath stringByAppendingPathComponent:self.databaseFilename_SHM]; return [self.oldDatabaseDirPath stringByAppendingPathComponent:self.databaseFilename_SHM];
} }
- (NSString *)oldDatabaseFilePath_WAL + (NSString *)oldDatabaseFilePath_WAL
{ {
return [self.oldDatabaseDirPath stringByAppendingPathComponent:self.databaseFilename_WAL]; return [self.oldDatabaseDirPath stringByAppendingPathComponent:self.databaseFilename_WAL];
} }
- (NSString *)newDatabaseFilePath + (NSString *)newDatabaseFilePath
{ {
return [self.newDatabaseDirPath stringByAppendingPathComponent:self.databaseFilename]; return [self.newDatabaseDirPath stringByAppendingPathComponent:self.databaseFilename];
} }
- (NSString *)newDatabaseFilePath_SHM + (NSString *)newDatabaseFilePath_SHM
{ {
return [self.newDatabaseDirPath stringByAppendingPathComponent:self.databaseFilename_SHM]; return [self.newDatabaseDirPath stringByAppendingPathComponent:self.databaseFilename_SHM];
} }
- (NSString *)newDatabaseFilePath_WAL + (NSString *)newDatabaseFilePath_WAL
{ {
return [self.newDatabaseDirPath stringByAppendingPathComponent:self.databaseFilename_WAL]; return [self.newDatabaseDirPath stringByAppendingPathComponent:self.databaseFilename_WAL];
} }
- (NSString *)dbPath + (void)migrateToSharedData
{ {
[OWSFileSystem moveAppFilePath:self.oldDatabaseFilePath [OWSFileSystem moveAppFilePath:self.oldDatabaseFilePath
sharedDataFilePath:self.newDatabaseFilePath sharedDataFilePath:self.newDatabaseFilePath
@ -461,32 +463,13 @@ void setDatabaseInitialized()
[OWSFileSystem moveAppFilePath:self.oldDatabaseFilePath_WAL [OWSFileSystem moveAppFilePath:self.oldDatabaseFilePath_WAL
sharedDataFilePath:self.newDatabaseFilePath_WAL sharedDataFilePath:self.newDatabaseFilePath_WAL
exceptionName:TSStorageManagerExceptionName_CouldNotMoveDatabaseFile]; exceptionName:TSStorageManagerExceptionName_CouldNotMoveDatabaseFile];
}
NSFileManager *fileManager = [NSFileManager defaultManager]; - (NSString *)dbPath
BOOL hasAllNewFiles = ([fileManager fileExistsAtPath:self.newDatabaseFilePath] && {
[fileManager fileExistsAtPath:self.newDatabaseFilePath_SHM] && DDLogVerbose(@"databasePath: %@", TSStorageManager.newDatabaseFilePath);
[fileManager fileExistsAtPath:self.newDatabaseFilePath_WAL]);
BOOL hasAnyNewFiles = ([fileManager fileExistsAtPath:self.newDatabaseFilePath] ||
[fileManager fileExistsAtPath:self.newDatabaseFilePath_SHM] ||
[fileManager fileExistsAtPath:self.newDatabaseFilePath_WAL]);
if (!hasAllNewFiles && !hasAnyNewFiles) {
for (NSString *filePath in @[
self.newDatabaseFilePath,
self.newDatabaseFilePath_SHM,
self.newDatabaseFilePath_WAL,
self.newDatabaseFilePath,
self.newDatabaseFilePath_SHM,
self.newDatabaseFilePath_WAL,
]) {
DDLogInfo(@"%@ Database file %@ exists %d", self.logTag, filePath, [fileManager fileExistsAtPath:filePath]);
}
OWSFail(@"%@ Incomplete set of database files.", self.logTag);
}
DDLogError(@"databasePath: %@", self.newDatabaseFilePath); return TSStorageManager.newDatabaseFilePath;
[DDLog flushLog];
return self.newDatabaseFilePath;
} }
+ (BOOL)isDatabasePasswordAccessible + (BOOL)isDatabasePasswordAccessible

View File

@ -3,6 +3,7 @@
// //
#import "AppVersion.h" #import "AppVersion.h"
#import <SignalServiceKit/NSUserDefaults+OWS.h>
NSString *const kNSUserDefaults_FirstAppVersion = @"kNSUserDefaults_FirstAppVersion"; NSString *const kNSUserDefaults_FirstAppVersion = @"kNSUserDefaults_FirstAppVersion";
NSString *const kNSUserDefaults_LastAppVersion = @"kNSUserDefaults_LastVersion"; NSString *const kNSUserDefaults_LastAppVersion = @"kNSUserDefaults_LastVersion";
@ -36,24 +37,22 @@ NSString *const kNSUserDefaults_LastCompletedLaunchAppVersion = @"kNSUserDefault
// The version of the app when it was first launched. // The version of the app when it was first launched.
// nil if the app has never been launched before. // nil if the app has never been launched before.
self.firstAppVersion = [[NSUserDefaults standardUserDefaults] objectForKey:kNSUserDefaults_FirstAppVersion]; self.firstAppVersion = [[NSUserDefaults appUserDefaults] objectForKey:kNSUserDefaults_FirstAppVersion];
// The version of the app the last time it was launched. // The version of the app the last time it was launched.
// nil if the app has never been launched before. // nil if the app has never been launched before.
self.lastAppVersion = [[NSUserDefaults standardUserDefaults] objectForKey:kNSUserDefaults_LastAppVersion]; self.lastAppVersion = [[NSUserDefaults appUserDefaults] objectForKey:kNSUserDefaults_LastAppVersion];
self.lastCompletedLaunchAppVersion = self.lastCompletedLaunchAppVersion =
[[NSUserDefaults standardUserDefaults] objectForKey:kNSUserDefaults_LastCompletedLaunchAppVersion]; [[NSUserDefaults appUserDefaults] objectForKey:kNSUserDefaults_LastCompletedLaunchAppVersion];
// Ensure the value for the "first launched version". // Ensure the value for the "first launched version".
if (!self.firstAppVersion) { if (!self.firstAppVersion) {
self.firstAppVersion = self.currentAppVersion; self.firstAppVersion = self.currentAppVersion;
[[NSUserDefaults standardUserDefaults] setObject:self.currentAppVersion [[NSUserDefaults appUserDefaults] setObject:self.currentAppVersion forKey:kNSUserDefaults_FirstAppVersion];
forKey:kNSUserDefaults_FirstAppVersion];
} }
// Update the value for the "most recently launched version". // Update the value for the "most recently launched version".
[[NSUserDefaults standardUserDefaults] setObject:self.currentAppVersion [[NSUserDefaults appUserDefaults] setObject:self.currentAppVersion forKey:kNSUserDefaults_LastAppVersion];
forKey:kNSUserDefaults_LastAppVersion]; [[NSUserDefaults appUserDefaults] synchronize];
[[NSUserDefaults standardUserDefaults] synchronize];
DDLogInfo(@"%@ firstAppVersion: %@", self.logTag, self.firstAppVersion); DDLogInfo(@"%@ firstAppVersion: %@", self.logTag, self.firstAppVersion);
DDLogInfo(@"%@ lastAppVersion: %@", self.logTag, self.lastAppVersion); DDLogInfo(@"%@ lastAppVersion: %@", self.logTag, self.lastAppVersion);
@ -68,9 +67,9 @@ NSString *const kNSUserDefaults_LastCompletedLaunchAppVersion = @"kNSUserDefault
self.lastCompletedLaunchAppVersion = self.currentAppVersion; self.lastCompletedLaunchAppVersion = self.currentAppVersion;
// Update the value for the "most recently launch-completed version". // Update the value for the "most recently launch-completed version".
[[NSUserDefaults standardUserDefaults] setObject:self.currentAppVersion [[NSUserDefaults appUserDefaults] setObject:self.currentAppVersion
forKey:kNSUserDefaults_LastCompletedLaunchAppVersion]; forKey:kNSUserDefaults_LastCompletedLaunchAppVersion];
[[NSUserDefaults standardUserDefaults] synchronize]; [[NSUserDefaults appUserDefaults] synchronize];
} }
- (BOOL)isFirstLaunch - (BOOL)isFirstLaunch

View File

@ -0,0 +1,17 @@
//
// Copyright (c) 2017 Open Whisper Systems. All rights reserved.
//
NS_ASSUME_NONNULL_BEGIN
@interface NSUserDefaults (OWS)
+ (NSUserDefaults *)appUserDefaults;
+ (void)migrateToSharedUserDefaults;
+ (void)removeAll;
@end
NS_ASSUME_NONNULL_END

View File

@ -0,0 +1,37 @@
//
// Copyright (c) 2017 Open Whisper Systems. All rights reserved.
//
#import "NSUserDefaults+OWS.h"
NS_ASSUME_NONNULL_BEGIN
@implementation NSUserDefaults (OWS)
+ (NSUserDefaults *)appUserDefaults
{
return [[NSUserDefaults alloc] initWithSuiteName:@"group.org.whispersystems.signal.group"];
}
+ (void)migrateToSharedUserDefaults
{
NSUserDefaults *appUserDefaults = self.appUserDefaults;
NSDictionary<NSString *, id> *dictionary = [NSUserDefaults standardUserDefaults].dictionaryRepresentation;
for (NSString *key in dictionary) {
id value = dictionary[key];
OWSAssert(value);
[appUserDefaults setObject:value forKey:key];
}
}
+ (void)removeAll
{
NSString *appDomain = NSBundle.mainBundle.bundleIdentifier;
[NSUserDefaults.standardUserDefaults removePersistentDomainForName:appDomain];
// TODO: How to clear the shared user defaults?
}
@end
NS_ASSUME_NONNULL_END