首页 / IOS / iOS应用千万级架构:存储持久化
iOS应用千万级架构:存储持久化
内容导读
互联网集市收集整理的这篇技术教程文章主要介绍了iOS应用千万级架构:存储持久化,小编现在分享给大家,供广大互联网技能从业者学习和参考。文章包含5189字,纯文字阅读大概需要8分钟。
内容图文
应用场景
iOS10后,发现在大量用户在NSUserDefaults中取值失败,导致一系列的持久化状态丢失。故切换到SQLitie3持久化更适合大型项目的使用。
场景一:在大型项目中,经常需要我们写的代码支持可降级,对一些新功能进行灰度验证。那运营开关是必不可少的。运营开关的配置就需要持久化设置了,即时网络异常,也需要读取上一次的正常记录的。
场景二:在大型项目中,有一些资源是需要动态配置的,那就可以集中放在一个接口里处理。比如大促的动态图、资源背景图、弹窗提示文案等。当接口异常时,需要读取本地数据库里上次存储的
场景三:用户的常规操作设置,也需要持久化记录,比如,新手指引弹框,当用户点了不再提醒,就应该记录到本地,下次不再提醒。还有就是超过多少次,不再提醒等一下用户的设置
场景四:需要全局使用的数据,也可以放到内存中,但不存入数据库,只当是内存的一个单例管理。
具体思路
- 依赖第三方库FMDB,YYModel
- 基于FMDB,按业务建立不同的数据表,将需要持久化的数据,通过key-Value的存储方式,存储到sqlite3数据库中
- 全局状态量均由VSPreference这个单例来进行管理,拆分为5个模块: defaultPreference / dynamicPreference / memoryPreference / switchPreference / userPreference
- APP启动,将sqlite3的数据加载到VSPreference中
场景及数据表说明
1.defaultPreference(VSDefaultPreference)
用于管理需要持久化的普通状态量,可理解为不属于这4个模块(dynamicPreference / memoryPreference / switchPreference / userPreference)的状态量。
2.dynamicPreference(VSDynamicPreference)
动态资源,APP动态配置的资源,APP启动时,请求接口返回
3.memoryPreference(VSMemoryPreference)
用于管理不需要持久化的配置项。
4.switchPreference(VSSwitchPreference)
运营开关,降级开关,APP启动时请求接口返回
5.userPreference(VSUserPreference)
用于管理记录用户行为的配置项,如:记录提示页是否展示过,记录提示页上次展示的时间……
VSPreference全局单例类
全局单例类,管理上面5个模块场景
@interface VSPreference : NSObject /* * 用于管理需要持久化的普通状态量,可理解为不属于这4个模块(dynamicPreference / memoryPreference / switchPreference / userPreference)的状态量 */ + (VSDefaultPreference *)defaultPreference; /** 动态资源,APP动态配置的资源,APP启动时,请求接口返回 */ + (VSDynamicPreference *)dynamicPreference; /** 用于管理不需要持久化的配置项,仅存在内存中。比如某个接口数据返回,需要记录某个字段的值 */ + (VSMemoryPreference *)memoryPreference; /** 运营开关,降级开关,APP启动时请求接口返回 */ + (VSSwitchPreference *)switchPreference; /** 用于管理记录用户行为的配置项,如:记录提示页是否展示过,记录提示页上次展示的时间 */ + (VSUserPreference *)userPreference; @end
底层结构
1. VSKeyValueStack
轻量级的用于单例化FMDatabaseQueue的堆栈类,基于Key-Value的存储方式,做了一些定制化的优化配置。
主要方法:
// 给数据表增加一个key-value void VSKeyValueSetKeyValueToTable(FMDatabase *db, NSString *key, id value, NSString *tableName) { NSDictionary<NSString *, id> *JSONObject = @{ key: value }; // [JSONObject yy_modelToJSONData]可能是因为多线程修改了内容导致崩溃 NSData *data = [[JSONObject copy] yy_modelToJSONData]; if (!data) { #if DEBUG dispatch_async(dispatch_get_main_queue(), ^{ @throw [NSException exceptionWithName:@"Key-Value 不是有效的JSON对象(上报到RTX吧)" reason:@"保持统一性" userInfo:nil]; }); #endifreturn; } NSString *SQLScript = [NSString stringWithFormat:kSQLFormatterForReplaceValue, tableName, key]; [db executeUpdate:SQLScript, data]; } // 从数据表里删除key-valuevoid VSKeyValueRemoveKeyValueToTable(FMDatabase *db, NSString *key, NSString *tableName) { NSString *SQLScript = [NSString stringWithFormat:kSQLFormatterForDeleteValue, tableName, key]; [db executeUpdate:SQLScript]; }
2. NSObject+VSKeyValueModel
用于基于KeyValueStack的ORM,具体使用方法可参考代码中的例子。
最主要的方法是,需要给每个属性添加KVO监听,当接口数据回来或者属性的值有变化时,就会触发KVO监听方法,从而更新数据库
/* * * 监听值的变化 * 1、将需要变化的keyValue都存储到VSKeyValueStackCachedChangeObjects中 * 2、每隔1秒,将VSKeyValueStackCachedChangeObjects中的keyValue拷贝到局部变量cachedChangeObjects中,并清空VSKeyValueStackCachedChangeObjects里面所有的数据 * 3、将cachedChangeObjects循环存储到sqlite中 */ - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id<VSKeyValueModel>)object change:(NSDictionary<NSString *, id> *)change context:(void *)context { if (context != VSKeyValueStackObserverContext) { return; } void(^batchHandler)(void) = ^(void) { UIBackgroundTaskIdentifier __block taskToken = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:NULL]; dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1 * NSEC_PER_SEC)), VSKeyValueStackCachedChangeQueue, ^{ NSArray<__VSKeyValueChange *> *cachedChangeObjects = [VSKeyValueStackCachedChangeObjects copy]; [VSKeyValueStackCachedChangeObjects removeAllObjects]; [self handleTransaction:^(FMDatabase *db) { for (__VSKeyValueChange *__change in cachedChangeObjects) { @autoreleasepool { if (IsEmpty(__change.value)) { VSKeyValueRemoveKeyValueToTable(db, __change.key, __change.tableName); } else { VSKeyValueSetKeyValueToTable(db, __change.key, __change.value, __change.tableName); } } } [[UIApplication sharedApplication] endBackgroundTask:taskToken]; taskToken = UIBackgroundTaskInvalid; }]; }); }; id value = change[NSKeyValueChangeNewKey]; dispatch_async(VSKeyValueStackCachedChangeQueue, ^{ if (!VSKeyValueStackCachedChangeObjects.count) { batchHandler(); } __VSKeyValueChange *__change = [__VSKeyValueChange new]; __change.tableName = [object keyValueTableName]; __change.key = keyPath; __change.value = value; [VSKeyValueStackCachedChangeObjects addObject:__change]; }); }
使用方法
1. 新建一个VSDemoPreference,实现协议VSKeyValueModel
2. 在VSDemoPreference.h 中添加你需要存入数据库的字段名,当然也可以存入数组和字典
3. 在VSDemoPreference.m 中,给 -initWithKeyValueStack 初始化方法的所有属性加上KVO监听、dealloc 的时候移除监听、实现协议keyValueTableName返回数据库表名、如果有默认值,在
setUpWithDefaultValue设置。
@implementation VSUserPreference - (instancetype)initWithKeyValueStack { self = [super initWithKeyValueStack]; if (self) { [self addKeyPathObserverToKeyValueStack]; } return self; } - (void)dealloc { [self removeKeyPathObserverFromKeyValueStack]; } #pragma mark - <VSKeyValueModel> - (NSString *)keyValueTableName { return@"UserPreference"; } // 设置属性默认值 - (void)setUpWithDefaultValue { _themeStyle = 0; _checkoutAgreeProtocolsMap = @{}; } @end
原文:https://www.cnblogs.com/jys509/p/13257950.html
内容总结
以上是互联网集市为您收集整理的iOS应用千万级架构:存储持久化全部内容,希望文章能够帮你解决iOS应用千万级架构:存储持久化所遇到的程序开发问题。 如果觉得互联网集市技术教程内容还不错,欢迎将互联网集市网站推荐给程序员好友。
内容备注
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 gblab@vip.qq.com 举报,一经查实,本站将立刻删除。
内容手机端
扫描二维码推送至手机访问。