菜鸟提问,关于userDefault的机制问题

leeambition@gmail.com 发布于 2013年11月21日 | 更新于 2013年11月21日
无人欣赏。

论坛里的少年们好,有两个问题想要请教:我先用注释部分向ud(userDefaults)里写入数据,然后将其注释重新编译运行。多次运行,打印的结果都如下 1.看文档说,ud返回的类型为immutable,但是如果用mutable类型接受objectForKey的返回值没有警告,而且竟然可以进行mutable特有的操作。2.再次从ud取数据,结果是受刚才mutable操作的影响。(但是实际上沙盒目录文件不受影响,我就想是不是从ud中取数据不一定走的硬盘),谢谢 @ibuick 如果在23-24行间加入synchronize plist文件还是不受影响 alt text

共8条回复
nickel 回复于 2013年11月21日

没完全听清楚你所描述的内容。

不知道楼主写过c/c++没有,一个传入参数或者返回值定义成const XXX的话,意味着不希望参数使用者去修改这个参数的值,即所谓“只读”。但其实这个只是编译时的限定,不是运行时限定。意思是如果你直接const数据进行修改,编译出错,但你强制转换后编译就通过了,实际运行时是绝对没有不会报错的(除非你因为你修改数据后造成的地址错误或者业务逻辑错误)。

我大概理解是你的问题与这个情况一致,所谓的mutable/immutable其实只是编译时的限制,你非要强制转换的话是没有问题的。

adad184 回复于 2013年11月21日

我的理解

userDefault会在初始化的时候读取文件(一个plist) 这里读取的所有NSArray 和 NSDictionary都是immutable的

但是userDefault本身也是一个Dictionary 所以在内存中时 你可以set mutable对象进去 只要在内存里都是不受限制的

但是在synchronize时 所有的mutable对象都会被当成immutable来写 所以 在之前初始化的时候 都会被读成immutable的

所以 当你用的时候 最好这样用

[[APP.userDefaults objectForKey:kUserDefaultUser] mutableCopy];
leeambition@gmail.com 回复于 2013年11月21日

2楼 @adad184 1楼 @nickel 不好意思 图裂了。。。。。 等我重新上图

leeambition@gmail.com 回复于 2013年11月21日

1楼 @nickel 运行没问题

leeambition@gmail.com 回复于 2013年11月21日

2楼 @adad184 是class cluster 你说的我同意 但是偶想知道userDefaults的工作原理

adad184 回复于 2013年11月21日

At runtime, you use an NSUserDefaults object to read the defaults that your application uses from a user’s defaults database. NSUserDefaults caches the information to avoid having to open the user’s defaults database each time you need a default value. The synchronize method, which is automatically invoked at periodic intervals, keeps the in-memory cache in sync with a user’s defaults database.

Values returned from NSUserDefaults are immutable, even if you set a mutable object as the value. For example, if you set a mutable string as the value for "MyStringDefault", the string you later retrieve using stringForKey: will be immutable.

A defaults database is created automatically for each user. The NSUserDefaults class does not currently support per-host preferences. To do this, you must use the CFPreferences API (see Preferences Utilities Reference). However, NSUserDefaults correctly reads per-host preferences, so you can safely mix CFPreferences code with NSUserDefaults code.

文档似乎写得很清楚了

yuzhouwww 回复于 2013年11月21日

5楼 @leeambition#gmail.com

首次读取userDefaults会读到内存中,下次再取都是走内存。 保存时会先写到内存,系统会在“合适”的时候自动序列化到闪存,也可以手动synchronize,序列化后可变性丢失。 所以当你保存一个可变对象时,写到内存中时还是可变的,写到闪存中时已经不可变了,从闪存中读出来的也是不可变的。

leeambition@gmail.com 回复于 2013年11月21日

已解决 THX

6楼 @adad184

7楼 @yuzhouwww

登录 或者 注册