详解 NSUserDefaults

发布于 2021-03-01 12:58:13 字数 5735 浏览 1255 评论 0

每次读取把所有内容吞进内存,直接在内存操作,再一次性覆盖文件,不适合存大量数据,就是plist保存到本地的,它自己会隔一段时间保存到本地,为保证时效,自己调用 synchronize

registerDefaults

当使用 NSUserDefaults 读取值时,当它没有设定时走默认值。

设置的默认值是不是持久化存储的,每次启动App的时候都要设置一次。

Domain

当我们调用 [NSUserDefaults standardUserDefaults] 方法时,它就会初始化,并且它默认会包含5个Domain,分别:

  • NSArgumentDomain 命令行参数,可以在Xcode中设置
  • Application App中存取的值
  • NSGlobalDomain
  • Languages 语言的相关信息
  • NSRegistrationDomain 注册默认值

在 NSUserDefaults 中我们可以看到 NSArgumentDomain、NSGlobalDomain、NSRegistrationDomain三个域。

- (void)setInteger:(NSInteger)value forKey:(NSString *)defaultName;
/// -setFloat:forKey: is equivalent to -setObject:forKey: except that the value is converted from a float to an NSNumber.
- (void)setFloat:(float)value forKey:(NSString *)defaultName;
/// -setDouble:forKey: is equivalent to -setObject:forKey: except that the value is converted from a double to an NSNumber.
- (void)setDouble:(double)value forKey:(NSString *)defaultName;

调用set方法都是存储在Application这个域中的。

查看 GNU 的 NSUserDefaults 方法实现:

/*
  * Set up search list (excluding language list, which we don't know yet)
  */
 [defs->_searchList addObject: GSPrimaryDomain];
 [defs->_searchList addObject: NSArgumentDomain];
 [defs->_searchList addObject: processName];
 [defs persistentDomainForName: processName];
 [defs->_searchList addObject: NSGlobalDomain];
 [defs persistentDomainForName: NSGlobalDomain];
 [defs->_searchList addObject: GSConfigDomain];
 [defs->_searchList addObject: NSRegistrationDomain];

 /* Load persistent data into the new instance.
  */
 [defs synchronize];

 /*
  * Look up user languages list and insert language specific domains
  * into search list before NSRegistrationDomain
  */
 uL = [defs stringArrayForKey: @"NSLanguages"];

//注释
 * <deflist>
 *   <term><code>GSPrimaryDomain</code> ... volatile</term>
 *   <desc>
 *     Contains values set at runtime and intended to supercede any values
 *     set in other domains.  This should be used with great care since it
 *     overrides values which may have been set explicitly by the user.
 *   </desc>
 *   <term><code>NSArgumentDomain</code> ... volatile</term>
 *   <desc>
 *     Contains defaults read from the arguments provided
 *     to the application at startup.<br />
 *     Pairs of arguments are used for this, with the first argument in
 *     each pair being the name of a default (with a hyphen prepended)
 *     and the second argument of the pair being the value of the default.<br />
 *     NB. In GNUstep special arguments of the form <code>--GNU-Debug=...</code>
 *     are used to enable debugging.  Despite beginning with a hyphen, these
 *     are not treated as default keys.
 *   </desc>
 *   <term>Application (name of the current process) ... persistent</term>
 *   <desc>
 *     Contains application specific defaults, such as window positions.
 *     This is the domain used by the -setObject:forKey: method and is
 *     the domain normally used when setting preferences for an application.
 *   </desc>
 *   <term><code>NSGlobalDomain</code> ... persistent</term>
 *   <desc>
 *     Global defaults applicable to all applications.
 *   </desc>
 *   <term>Language (name based on users's language) ... volatile</term>
 *   <desc>
 *     Constants that help with localization to the users's
 *     language.
 *   </desc>
 *   <term><code>GSConfigDomain</code> ... volatile</term>
 *   <desc>
 *     Information retrieved from the GNUstep configuration system.
 *     Usually the system wide and user specific GNUstep.conf files,
 *     or from information compiled in when the base library was
 *     built.<br />
 *     In addition to this standard configuration information, this
 *     domain contains all values from property lists store in the
 *     GlobalDefaults subdirectory or from the GlobalDefaults.plist file
 *     stored in the same directory as the system wide GNUstep.conf
 *     file.
 *   </desc>
 *   <term><code>NSRegistrationDomain</code> ... volatile</term>
 *   <desc>
 *     Temporary defaults set up by the application.
 *   </desc>
 * </deflist>

发现读取数据时,会在底层的数据结构进行一次搜索,它的顺序是这样:

NSArgumentDomain -> Application -> NSGlobalDomain -> Languages -> NSRegistrationDomain

应用

根据以上加载顺序,我们就可以实现语言不跟系统同步的功能,这就是 NSUserDefaults 分层设计的好处。

在命令行参数中做手脚。微信的语言不跟随系统同步是不是也是这个思路呢,待落实。
Edit Scheme -> Arguments Passed On Launch 选项卡中添加命令行参数。格式如下:

For the purposes of debugging an app target, launch arguments and environment variables can be thought to be equivalent—both change the runtime behavior by defining certain values. In practice, the main difference between the two is that launch arguments begin with a dash (-) and don’t have a separate field for argument values.

栗子:-zll hao
在应用中我们可通过 [[NSUserDefaults standardUserDefaults] volatileDomainForName:NSArgumentDomain]; 获取设置的命令行参数
也可以通过 [[NSUserDefaults standardUserDefaults] dictionaryRepresentation] 获取 NSUserDefaults 所有数据

相关链接

NSUserDefaults - 熟悉与陌生
Launch Arguments & Environment Variables

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据

关于作者

JSmiles

生命进入颠沛而奔忙的本质状态,并将以不断告别和相遇的陈旧方式继续下去。

0 文章
0 评论
84961 人气
更多

推荐作者

娇女薄笑

文章 0 评论 0

biaggi

文章 0 评论 0

xiaolangfanhua

文章 0 评论 0

rivulet

文章 0 评论 0

我三岁

文章 0 评论 0

薆情海

文章 0 评论 0

    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文