OC—NSUserDefaults

简介:是iOS/macOS提供的轻量级键值持久化,适合存储用户偏好、小配置、状态标记等简单数据(不适合大体积数据活着复杂查询)。字符串、数字、数组、字典、日期、NSData,如果需要存储自定义对象,需要先把对象序列化为NSDAta(前面在讲解多界面传值有涉及)

使用示例:

NSUserDefaults *defs = [NSUserDefaults standardUserDefaults];
​
// 写
[defs setObject:@"Mike" forKey:@"username"];
[defs setInteger:28 forKey:@"age"];
[defs setBool:YES forKey:@"isLogin"];
/*
  数据会先存在内存里,系统会在适当时机自动写到
*/
​
// 读
NSString *name = [defs stringForKey:@"username"];
NSInteger age = [defs integerForKey:@"age"];
BOOL isLogin = [defs boolForKey:@"isLogin"];
​
// 删除某个键
[defs removeObjectForKey:@"username"];

不需要每次都调用synchronize方法(会强制立刻将内存的数据写入磁盘),避免频繁调用导致卡顿耗电增加,影响性能

注册默认值(fallback/注册域)

如果需要给没有存储过的键提供默认值,用registerDefaults:方法(在 app 启动处(application:didFinishLaunchingWithOptions:)注册默认值:)

NSDictionary *defaults = @{ @"theme": @"light", @"pageSize": @20 };
[[NSUserDefaults standardUserDefaults] registerDefaults:defaults];
/*这是只读回退,不会覆盖已有值,也不会写入磁盘*/

监听变化

当别的地方更改了偏好设置,我们想要自动更新UI时

// 注册监听(比如在 viewDidLoad)
[[NSNotificationCenter defaultCenter] addObserver:self
                                         selector:@selector(defaultsChanged:)
                                             name:NSUserDefaultsDidChangeNotification
                                           object:nil];
​
- (void)defaultsChanged:(NSNotification *)note {
    //这个通知不知道哪个key变了,需要自己再去读
    BOOL dark = [[NSUserDefaults standardUserDefaults] boolForKey:@"darkModeEnabled"];
    NSLog(@"偏好变了,darkMode=%d", dark);
}

如何找到是哪一个key改变了

这里我们不要直接使用系统自带的set方法存数据,我们自己实现一个存数据的方法,告诉外面改变的是哪一个key

1.我们写一个存的方法

- (void)mySetValue:(id)value forKey:(NSString *)key {
    [[NSUserDefaults standardUserDefaults] setObject:value forKey:key];
    [[NSNotificationCenter defaultCenter] postNotificationName:@"note"
                                                        object:nil
                                                      userInfo:@{@"key": key}];//告诉别人我们改变的是哪一个key
}

2.在需要知道变化的地方监听这个通知

[[NSNotificationCenter defaultCenter] addObserver:self
                                         selector:@selector(myKeyChanged:)
                                             name:@"note"
                                           object:nil];
​

3.在回调方法中取出key

- (void)myKeyChanged:(NSNotification *)note {
    NSString *changedKey = note.userInfo[@"key"];
    NSLog(@"有人改了 key=%@", changedKey);
}

存储自定义对象

除了在多界面传值那里的解当归档方法,这里再介绍使用JSON实现

NSDictionary *profile = @{@"name": @"Alice", @"age": @20};
NSData *json = [NSJSONSerialization dataWithJSONObject:profile options:0 error:nil];
[[NSUserDefaults standardUserDefaults] setObject:json forKey:@"profile"];
​
// 取出
NSData *saved = [[NSUserDefaults standardUserDefaults] objectForKey:@"profile"];
if (saved) {
    NSDictionary *obj = [NSJSONSerialization JSONObjectWithData:saved options:0 error:nil];
    NSLog(@"%@", obj);
}

获取所有键

// 打印所有
NSDictionary *all = [[NSUserDefaults standardUserDefaults] dictionaryRepresentation];
NSLog(@"所有键值: %@", all);
​
// 清空当前 App 的持久域(慎用)
NSString *bundleID = [[NSBundle mainBundle] bundleIdentifier];
[[NSUserDefaults standardUserDefaults] removePersistentDomainForName:bundleID];

拓展:

第一次访问某个域的时候,系统会把对应的plist加载到内存,后续读取都是查内存缓存,所以非常快。如果我们在同一进程里改值,那么再读取就是最新的,如果是跨进程,由于各自都有缓存,存在短暂不同步的窗口,但是并不影响

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值