Repository: Tencent/MMKV
File: iOS/MMKV/MMKV/MMKV.mm (Objective-C++)

Code before:

+ (instancetype)mmkvWithID:(NSString *)mmapID cryptKey:(NSData *)cryptKey {
	if (mmapID.length <= 0) {
		return nil;
	}
	CScopedLock lock(g_instanceLock);

	MMKV *kv = [g_instanceDic objectForKey:mmapID];
	if (kv == nil) {
		kv = [[MMKV alloc] initWithMMapID:mmapID cryptKey:cryptKey];
		[g_instanceDic setObject:kv forKey:mmapID];
	}
	return kv;
}

- (instancetype)initWithMMapID:(NSString *)mmapID cryptKey:(NSData *)cryptKey {
	if (self = [super init]) {
		m_lock = [[NSRecursiveLock alloc] init];

		m_mmapID = mmapID;

		m_path = [MMKV mappedKVPathWithID:m_mmapID];
		if (!isFileExist(m_path)) {
			createFile(m_path);
		}
		m_crcPath = [MMKV crcPathWithMappedKVPath:m_path];

		if (cryptKey.length > 0) {
			m_cryptor = new AESCrypt((const unsigned char *) cryptKey.bytes, cryptKey.length);
		}

		[self loadFromFile];

#ifdef __IPHONE_OS_VERSION_MIN_REQUIRED
		auto appState = [UIApplication sharedApplication].applicationState;
		if (appState == UIApplicationStateBackground) {
			m_isInBackground = YES;
		} else {
			m_isInBackground = NO;
		}
		MMKVInfo(@"m_isInBackground:%d, appState:%ld", m_isInBackground, (long) appState);

		[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(onMemoryWarning) name:UIApplicationDidReceiveMemoryWarningNotification object:nil];
		[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(didEnterBackground) name:UIApplicationDidEnterBackgroundNotification object:nil];
		[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(didBecomeActive) name:UIApplicationDidBecomeActiveNotification object:nil];
#endif
	}
	return self;
}

- (void)dealloc {

Review comment (security):
Doing creating inside a function named `canXXX` is confusing. Replace `createFile` with getting write permission of the specific location is better.

Code after:
+ (instancetype)mmkvWithID:(NSString *)mmapID cryptKey:(NSData *)cryptKey relativePath:(nullable NSString *)path {
    if (mmapID.length <= 0) {
        return nil;
    }
    if (![self canCreateMMKVPath:mmapID relativePath:path]) {
        return nil;
    }
    
    CScopedLock lock(g_instanceLock);
    
    NSString *kvKey = [self mmapKeyWithMMapID:mmapID relativePath:path];
    MMKV *kv = [g_instanceDic objectForKey:kvKey];
    if (kv == nil) {
        kv = [[MMKV alloc] initWithMMapID:mmapID cryptKey:cryptKey relativePath:path];
        [g_instanceDic setObject:kv forKey:kvKey];
    }
    return kv;
}

+ (BOOL)canCreateMMKVPath:(NSString *)mmapID relativePath:(nullable NSString *)relativePath {
    if (relativePath) {
        NSString *path = [MMKV mappedKVPathWithID:mmapID relativePath:relativePath];
        if (isFileExist(path)) {
            return true;
        } else {
            BOOL ret = createFile(path);
            return ret;
        }
    } else {
        return true;
    }
}

+ (NSString *)mmapKeyWithMMapID:(NSString *)mmapID relativePath:(nullable NSString *)relativePath {
    NSString *string = nil;
    if ([relativePath length] > 0) {
        string = md5([relativePath stringByAppendingPathComponent:mmapID]);
    } else {
        string = mmapID;
    }
    MMKVInfo(@"%s mmapKey: %@", __PRETTY_FUNCTION__, string);
    return string;
}

- (instancetype)initWithMMapID:(NSString *)mmapID cryptKey:(NSData *)cryptKey relativePath:(nullable NSString *)relativePath {
    if (self = [super init]) {
        m_lock = [[NSRecursiveLock alloc] init];
        
        m_mmapID = [MMKV mmapKeyWithMMapID:mmapID relativePath:relativePath];
        
        m_path = [MMKV mappedKVPathWithID:mmapID relativePath:relativePath];