NSUserDefaults的suitename / 2020-08-27

直接使用[NSUserDefaults standardUserDefaults]的接口可以很方便地存取字符串、数值以及序列化的二进制数据。但当APP功能足够复杂模块足够多之后,我们可能需要使用initWithSuiteName接口操作不同[域]下的NSUserDefaults。

我们通常使用NSUserDefaults来存储一些偏好设置和用户数据,直接使用[NSUserDefaults standardUserDefaults]的接口可以很方便地存取字符串、数值以及序列化的二进制数据。在多数情况下,这样操作问题不大,但当APP功能足够复杂模块足够多之后,总是使用[NSUserDefaults standardUserDefaults]的接口并不是一个好的选择。

实际上,[NSUserDefaults standardUserDefaults]操作的是APP沙箱中Library/Preferences目录下的以bundle id命名的plist文件。假设一个很复杂的APP,集成了很多SDK,这些SDK中或多或少的都会用到[NSUserDefaults standardUserDefaults]的接口,这样会带来以下几个问题:

  • 各个SDK需要保证设置数据KEY的唯一性,以防止存取冲突;
  • plist文件越来越大造成的读写效率问题;
  • 无法便捷的清除由某一个SDK创建的NSUserDefaults数据;

针对这个问题,可以考虑使用initWithSuiteName接口。

- (nullable instancetype)initWithSuiteName:(nullable NSString *)suitename

这个接口的参数有四种情况:

  • 传入nil

和[NSUserDefaults standardUserDefaults]一样,操作的是Documents/Library/Preferences目录下以bundle id命名的plist文件。

  • 传入bundle id

无效,会返回nil。

  • 传入App Groups配置中Group ID

会操作APP的共享目录中创建的plist文件,方便跨APP或宿主APP与扩展应用之间共享数据。

  • 传入其他值

操作的是沙箱的Documents/Library/Preferences目录下以suitename命名的plist文件。

在大型APP的各个SDK开发中,只需要传入不同的suitename,即可操作不同的plist文件,可以解决上面的问题:

  • 因为是操作的不同的plist文件,key自然是可以重复的;
  • 将原本写入一个文件中的数据分散在不同的文件,提升存取效率;
  • 可以通过removePersistentDomainForName接口移除指定suitename的全部数据,即清空指定plist文件而对其他文件没有干扰。

其它文章

iOS TestFlight的局限性及改进措施
iOS APP灰度发布方案
iOS 13 Scene Delegate and multiple windows
iOS Sign With Apple实践