替换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的方案的更多相关文章

  1. CS5216PIN TO PIN替换PS8402A方案|PS8402A电路设计原理图|CS5216芯片

    PS8402A是HDMI 电平移位器/中继器专为2型双模Display Port(DP++)电缆适配器应用而设计.它设计用于Display Port到DVI或Display Port到HDMI的2型适 ...

  2. 通过修改 LayoutInflater,全局替换字体!!!

    序 在 Android 下使用自定义字体已经是一个比较常见的需求了,最近也做了个比较深入的研究. 那么按照惯例我又要出个一篇有关 Android 修改字体相关的文章,但是写下来发现内容还挺多的,所以我 ...

  3. Freeline--Android平台上的秒级编译方案

    Freeline 技术揭秘 Freeline是什么? Freeline是蚂蚁金服旗下一站式理财平台蚂蚁聚宝团队15年10月在Android平台上的量身定做的一个基于动态替换的编译方案,5月阿里集团内部 ...

  4. Android Freeline加速编译App方案 使用和总结

    Freeline简单介绍 在Android Studio还没推出Instant Run功能之前,每次改动Android project项目时都要将整个项目又一次编译一次,然后再将资源和代码文件打包成A ...

  5. 热修复-Tinker

    微信开源,真是喜出望外,必须要去看看啊,比起nuwa来微信好很多,而且github上也有专门的官方文档说明,还有很多资料查询 参考地址:https://github.com/Tencent/tinke ...

  6. 【流量劫持】SSLStrip 终极版 —— location 瞒天过海

    前言 之前介绍了 HTTPS 前端劫持 的方案,虽然很有趣,然而现实却并不理想.其唯一.也是最大的缺陷,就是无法阻止脚本跳转.若是没有这个缺陷,那就非常完美了 -- 当然也就没有必要写这篇文章了. 说 ...

  7. kafka(logstash) + elasticsearch 构建日志分析处理系统

    第一版:logstash + es 第二版:kafka 替换 logstash的方案

  8. php性能优化

    序   很长时间没有写博文了,最近换了工作,长时间加班,根本没有时间做其他事情!今天闲下来了,想一想php性能方面的事情.这也是我2014年的第一篇博文! 推荐阅读:初学者到中级者应该掌握的!   p ...

  9. Android热修复技术选型(不在市场发布新版本的情况下,直接更新app)

    2015年以来,Android开发领域里对热修复技术的讨论和分享越来越多,同时也出现了一些不同的解决方案,如QQ空间补丁方案.阿里AndFix以及微信Tinker,它们在原理各有不同,适用场景各异,到 ...

随机推荐

  1. 【linux】sed -e 's/-//g'

    sed是用来处理文本的 s/正则表达式/替换字符串/    :表示将正则表达式的内容替换为后面的字符串 g    :表示替换全部,即如果不加g,则只会替换第一个 -e    :多点编辑(这个没懂) 例 ...

  2. 说一下PHP中die()和exit()区别

    PHP手册:die()Equivalent to exit(). 说明:die()和exit()都是中止脚本执行函数:其实exit和die这两个名字指向的是同一个函数,die()是exit()函数的别 ...

  3. How to return plain text from AWS Lambda & API Gateway

    With limited experience in AWS Lambda & API Gateway, it's struggling to find the correct way to ...

  4. dojo/domReady! 中感叹号的作用

    废话 其实不算个技术问题,但实在是花了我不少时间,不记下来都对不起我这浪费掉的几十分钟. 问题 在dojo官网上看教程,跟着做点练习,看到Dojo DOM Functions那节,有一个练习是改变页面 ...

  5. java 报错英文

    —————————— ASP.Net+Android+IOS开发..Net培训.期待与您交流! —————————— 第一章:JDK(Java Development Kit) java开发工具包 J ...

  6. js 把数组对象按照某个属性进行排序

    var arr=[{a:1},{a:3},{a:2}]; function objSort(prop){ return function (obj1, obj2) { var val1 = obj1[ ...

  7. linux学习笔记-7.文件属性

    1.查看文件夹属性 ls -ld test 2.文件夹的rwx --x:可以cd进去r-x:可以cd进去并ls-wx:可以cd进去并touch,rm自己的文件,并且可以vi其他用户的文件-wt:可以c ...

  8. url后面添加参数,注意&?的添加方式

    // 添加参数&key=value 直接输出url function insertParam(key, value) { key = encodeURI(key); value = encod ...

  9. 关于ListView中EditText在软键盘弹出后的焦点问题

    转自:http://www.cnblogs.com/haofei/p/3305030.html 在ListView中,每次弹出软键盘后就会重新调用getView()方法,导致EditText失去焦点. ...

  10. Failed to connect socket to '/var/run/libvirt/libvirt-sock'的问题解决

    1.增加libvirtd用户组 groupadd libvirtd 2.设置用户到组 sudo usermod -a -G libvirtd $USER 3.设置启动libvirtd服务的用户组 vi ...