替换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,它们在原理各有不同,适用场景各异,到 ...
随机推荐
- 线上SQL优化
最近在线上发现很多性能有问题的sql,开发写sql语句的时候,没充分考虑是否用上索引了,所以这个坑得DBA来填,好了,废话不多说,把一些线上的优化经验跟大家分享. 由于是线上的表,所以就不公开具体的表 ...
- 【论文阅读】ShuffleNet: An Extremely Efficient Convolutional Neural Network for Mobile Devices
ShuffleNet: An Extremely Efficient Convolutional Neural Network for MobileDevices
- Archlinux系统配置学习笔记(一)
本文档是有关Archlinux系统配置的学习笔记,参考和学习的是Archlinux官方网站上的相应文档:General Recommendations. 这里的配置主要是针对按照官方网站上的文档刚刚完 ...
- IDEA & Android Studio换主题背景
IDEA系列主题 http://www.riaway.com/index.phphttp://color-themes.com/?view=index 详细用法: https://www.jiansh ...
- GitLab备份的创建与恢复
使用Gitlab一键安装包安装Gitlab非常简单, 同样的备份恢复与迁移也非常简单. 使用一条命令即可创建完整的Gitlab备份: gitlab-rake gitlab:backup:create使 ...
- 【AtCoder】ARC093
C - Traveling Plan 相当于一个环,每次删掉i点到两边的距离,加上新相邻的两个点的距离 代码 #include <bits/stdc++.h> #define fi fir ...
- spring配置文件详解以及beans:beans标签
第一行的意思就是你这个文件的默认schema为security,所以你的beans定义就需要加上前缀beans 一般的定义文件默认都是beans: 下面是spring配置文件的详解: 转自:http: ...
- CSS------Filter属性的使用方法
转载: http://www.w3cplus.com/css3/ten-effects-with-css3-filter
- 少走弯路,一个老程序猿谈PHP职业发展规划
PHP是一个使用者非常多的开发语言,但在每个领域里的开发侧重点有所不同互联网方面,在稳定的基础上,更注重性能.高并发,高负载的处理. PHP职业发展规划一般有三条路线,一条技能专精发展路线.另两条,是 ...
- DJANGO ADMIN 一些有用的设置(转)
DJANGO ADMIN 一些有用的设置 Django自带的后台管理是Django明显特色之一,可以让我们快速便捷管理数据.后台管理可以在各个app的admin.py文件中进行控制.以下是我最近摸 ...