替换NSUserDefaults的方案
替换NSUserDefaults的方案

效果

源码
https://github.com/YouXianMing/iOS-Utilities
//
// BaseValueStorageManager.h
// ValueStorageManager
//
// Created by YouXianMing on 16/3/17.
// Copyright © 2016年 YouXianMing. All rights reserved.
// #import <Foundation/Foundation.h>
#import "AbsEncryptingMode.h" @interface BaseValueStorageManager : NSObject /**
* Config the encryptingMode object and properties prefix, you should run this method first.
*
* @param encryptingMode EncryptingMode object.
* @param prefix Prefix string.
*/
+ (void)configEncryptingMode:(AbsEncryptingMode *)encryptingMode prefix:(NSString *)prefix; /**
* Get the shared instance.
*
* @return Shared instance.
*/
+ (instancetype)sharedInstance; @end
//
// BaseValueStorageManager.m
// ValueStorageManager
//
// Created by YouXianMing on 16/3/17.
// Copyright © 2016年 YouXianMing. All rights reserved.
// #import "BaseValueStorageManager.h"
#import "FastCoder.h"
#import <objc/runtime.h> static NSMutableDictionary *_dictionary = nil; @interface BaseValueStorageManager () @property (nonatomic, strong) NSArray *baseValueStorageManagerProperties;
@property (nonatomic, strong) AbsEncryptingMode *baseValueStorageManagerEncryptingMode;
@property (nonatomic, strong) NSString *baseValueStorageManagerPrifixName; @end @implementation BaseValueStorageManager + (void)initialize { if (self == [BaseValueStorageManager class]) { _dictionary = [NSMutableDictionary dictionary];
}
} + (void)configEncryptingMode:(AbsEncryptingMode *)encryptingMode prefix:(NSString *)prefix { BaseValueStorageManager *newObject = [[[self class] alloc] init];
newObject.baseValueStorageManagerEncryptingMode = (encryptingMode == nil ? [AbsEncryptingMode new] : encryptingMode);
newObject.baseValueStorageManagerPrifixName = (prefix == nil ? NSStringFromClass([self class]) : prefix); // Get all useful properties.
NSArray *allProperties = [newObject allProperties];
NSMutableArray *usefulProperties = [NSMutableArray array];
for (int i = ; i < allProperties.count; i++) { NSString *propertyName = allProperties[i];
if ([propertyName isEqualToString:@"baseValueStorageManagerProperties"] ||
[propertyName isEqualToString:@"baseValueStorageManagerEncryptingMode"] ||
[propertyName isEqualToString:@"baseValueStorageManagerPrifixName"]) { continue;
} [usefulProperties addObject:propertyName];
}
newObject.baseValueStorageManagerProperties = [NSArray arrayWithArray:usefulProperties]; [_dictionary setObject:newObject forKey:NSStringFromClass([self class])]; // Set all the properties.
for (int i = ; i < allProperties.count; i++) { NSString *key = allProperties[i];
NSString *ketPath = [newObject addPrifixWithString:key prifix:newObject.baseValueStorageManagerPrifixName];
id object = [[NSUserDefaults standardUserDefaults] objectForKey:ketPath]; if (object) { object = [FastCoder objectWithData:[newObject.baseValueStorageManagerEncryptingMode decryptData:object]];
[newObject setValue:object forKey:key];
}
} // KVO
for (int i = ; i < newObject.baseValueStorageManagerProperties.count; i++) { [newObject addObserver:newObject forKeyPath:newObject.baseValueStorageManagerProperties[i]
options:NSKeyValueObservingOptionNew context:nil];
}
} - (NSString *)addPrifixWithString:(NSString *)string prifix:(NSString *)prefix { return [NSString stringWithFormat:@"_%@_%@", prefix, string];
} + (instancetype)sharedInstance { return _dictionary[NSStringFromClass([self class])];
} - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSString *,id> *)change context:(void *)context { BaseValueStorageManager *manager = object;
NSString *newKeyPath = [manager addPrifixWithString:keyPath prifix:_baseValueStorageManagerPrifixName];
id newValue = [_baseValueStorageManagerEncryptingMode encryptData:[FastCoder dataWithRootObject:change[@"new"]]];
[[NSUserDefaults standardUserDefaults] setObject:newValue forKey:newKeyPath];
} /**
* Get all properties.
*
* @return Properties array.
*/
- (NSArray *)allProperties { u_int count;
objc_property_t *properties = class_copyPropertyList([self class], &count);
NSMutableArray *propertiesArray = [NSMutableArray arrayWithCapacity:count]; for (int i = ; i<count; i++) { const char *propertyName = property_getName(properties[i]);
[propertiesArray addObject:[NSString stringWithUTF8String: propertyName]];
} free(properties); return propertiesArray;
} - (void)dealloc { for (int i = ; i < self.baseValueStorageManagerProperties.count; i++) { [self removeObserver:self forKeyPath:self.baseValueStorageManagerProperties[i]];
}
} @end
细节

替换NSUserDefaults的方案的更多相关文章
- CS5216PIN TO PIN替换PS8402A方案|PS8402A电路设计原理图|CS5216芯片
PS8402A是HDMI 电平移位器/中继器专为2型双模Display Port(DP++)电缆适配器应用而设计.它设计用于Display Port到DVI或Display Port到HDMI的2型适 ...
- 通过修改 LayoutInflater,全局替换字体!!!
序 在 Android 下使用自定义字体已经是一个比较常见的需求了,最近也做了个比较深入的研究. 那么按照惯例我又要出个一篇有关 Android 修改字体相关的文章,但是写下来发现内容还挺多的,所以我 ...
- Freeline--Android平台上的秒级编译方案
Freeline 技术揭秘 Freeline是什么? Freeline是蚂蚁金服旗下一站式理财平台蚂蚁聚宝团队15年10月在Android平台上的量身定做的一个基于动态替换的编译方案,5月阿里集团内部 ...
- Android Freeline加速编译App方案 使用和总结
Freeline简单介绍 在Android Studio还没推出Instant Run功能之前,每次改动Android project项目时都要将整个项目又一次编译一次,然后再将资源和代码文件打包成A ...
- 热修复-Tinker
微信开源,真是喜出望外,必须要去看看啊,比起nuwa来微信好很多,而且github上也有专门的官方文档说明,还有很多资料查询 参考地址:https://github.com/Tencent/tinke ...
- 【流量劫持】SSLStrip 终极版 —— location 瞒天过海
前言 之前介绍了 HTTPS 前端劫持 的方案,虽然很有趣,然而现实却并不理想.其唯一.也是最大的缺陷,就是无法阻止脚本跳转.若是没有这个缺陷,那就非常完美了 -- 当然也就没有必要写这篇文章了. 说 ...
- kafka(logstash) + elasticsearch 构建日志分析处理系统
第一版:logstash + es 第二版:kafka 替换 logstash的方案
- php性能优化
序 很长时间没有写博文了,最近换了工作,长时间加班,根本没有时间做其他事情!今天闲下来了,想一想php性能方面的事情.这也是我2014年的第一篇博文! 推荐阅读:初学者到中级者应该掌握的! p ...
- Android热修复技术选型(不在市场发布新版本的情况下,直接更新app)
2015年以来,Android开发领域里对热修复技术的讨论和分享越来越多,同时也出现了一些不同的解决方案,如QQ空间补丁方案.阿里AndFix以及微信Tinker,它们在原理各有不同,适用场景各异,到 ...
随机推荐
- CF601A 【The Two Routes】
看数据范围,然后果断邻接矩阵$Floyd$啊 对于公路和铁路,各建一个图,分别跑最短路,然后取最大值即可 #include<iostream> #include<cstdio> ...
- Windows 10安装pip方法
pip是一款非常方便的python包管理工具,本文主要介绍在windows 10下安装pip方法. 1. 下载pip 地址:https://pypi.python.org/pypi/pip#downl ...
- PHP 操作redis 封装的类 转的
<?php/** * Redis 操作,支持 Master/Slave 的负载集群 * * @author jackluo */class RedisCluster{ // ...
- 【PAT】1032 Sharing (25)(25 分)
1032 Sharing (25)(25 分) To store English words, one method is to use linked lists and store a word l ...
- thinkphp中table方法
table方法也属于模型类的连贯操作方法之一,主要用于指定操作的数据表. 用法 一般情况下,操作模型的时候系统能够自动识别当前对应的数据表,所以,使用table方法的情况通常是为了:切换操作的数据表: ...
- Djang1.8+Python2.0迁移到Django2.0+Python3.6注意事项(转)
Djang1.8+Python2.0迁移到Django2.0+Python3.6注意事项 参考:https://blog.csdn.net/weixin_40475396/article/detail ...
- 洛谷P3576 [POI2014]MRO-Ant colony [二分答案,树形DP]
题目传送门 MRO-Ant colony 题目描述 The ants are scavenging an abandoned ant hill in search of food. The ant h ...
- JAVA 图形开发中组件对齐方法及界面开发
/*文章中用到的代码只是一部分,需要源码的可通过邮箱联系我 1978702969@qq.com*/ 在上篇博客中提到了JAVA图形界面开发时的两种布局,流式布局和边框布局. 在实际使用中可能会发现,往 ...
- C#开发Unity游戏教程之游戏对象的行为逻辑方法
C#开发Unity游戏教程之游戏对象的行为逻辑方法 游戏对象的行为逻辑——方法 方法(method),读者在第1章新建脚本时就见过了,而且在第2章对脚本做整体上的介绍时也介绍过,那么上一章呢,尽管主要 ...
- 「WC 2019」数树
「WC 2019」数树 一道涨姿势的EGF好题,官方题解我并没有完全看懂,尝试用指数型生成函数和组合意义的角度推了一波.考场上只得了 44 分也暴露了我在数数的一些基本套路上的不足,后面的 \(\ex ...