替换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,它们在原理各有不同,适用场景各异,到 ...
随机推荐
- 【转】ElasticSearch之定时删除数据
有的时候我们在使用ES时,由于资源有限或业务需求,我们只想保存最近一段时间的数据,所以有如下脚本可以定时删除数据 delete_es_by_day.sh #!/bin/sh # example: in ...
- ClouderaManager配置报警邮件
- 【noip模拟赛1】古韵之乞巧 (dp)
描述 闺女求天女,更阑意未阑. 玉庭开粉席,罗袖捧金盘. 向月穿针易,临风整线难. 不知谁得巧,明旦试相看. ——祖咏<七夕> 女子乞巧,是七夕的重头戏.古时,女子擅长女红被视为一种重要的 ...
- Qt判断网络是否在
我们已知的网络连接有3种:拨号.使用局域网以及代理上网. 无论哪一种上网方式都可以判断网络是否畅通,借此,我们来做一个判断网络是否畅通(存在)的程序,新建一个基类为QWidget的工程,不要UI. 添 ...
- MySQL 5.7基于GTID复制的常见问题和修复步骤(一)
[问题一] 复制slave报错1236,是较为常见的一种报错 Got fatal error 1236 from master when reading data from binary log: ' ...
- Vmaware复制后的虚拟机不能上网问题解决
最近在vmware上安装了一个xp虚拟机,想同时运行两个这样的虚拟机,于是想到了复制,将原来的虚拟机文件夹复制下来,然后在vmware中打开该文件扩展名为.vmx的虚拟机即可,但是发现却无法上网. 原 ...
- 【BZOJ-2888】资源运输 LCT + 启发式合并
2888: 资源运输 Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 63 Solved: 33[Submit][Status][Discuss] D ...
- c# -- 解决vs使用本地iis运行项目支持局域网访问的问题(附防火墙端口开放步骤)
用vs运行项目时,有时候需要局域网内不同设备进行访问调试~ 以前解决过这个问题,这次用了部新电脑,问题又出现了,改了配置还是不行,原来还差了一步防火墙端口开放访问. 于是写了这篇分享,备忘~ 操作步骤 ...
- U盘量产大致研究思路
这几天搞了一波U盘量产,很多年前玩的基本都是些皮毛,比如U盘分区,U盘启动,以及台电U盘的光驱启动等等,这些现在看起来其实都不入眼,只是简单的将U盘分个区,并且没玩到主控上面去. 下面是一些自己的理解 ...
- MikroTik RouterOS网址资源收集
routeros|mikrotik|ros|软路由论坛|中国路由网|软件路由|软件路由器|routeros技术论坛|路由论坛 - Powered by Discuz! Mikrotik RB450 ...