使用NSUserDefaults跨App间通信

NSUserDefaults是什么想必我应该不用多说了,相信每一个iOS开发都是知道并且能够熟练使用的(NSUserDefaults在Foundation框架中被定义,用来存储和读取一些轻量级数据。其本质是操作plist文件)。当然,说这些基础意义不大,今天我想说一点大部分人不知道的,那就是使用NSUserDefaults跨App间通信。

巧用SuiteName

- (nullable instancetype)initWithSuiteName:(nullable NSString *)suitename NS_AVAILABLE(10_9, 7_0) NS_DESIGNATED_INITIALIZER;

这个方法可能大部分人没有用过,它的作用是跨App间通信或者主App与Extension共享数据,一般配合使用的是App Groups。

App Groups数据共享
在两个项目Target里面的Signing & Capabilities中,将App Groups的SuiteName设置成一致的标识字符串(将两个App加入同一个Group)。

然后在两个App分别使用

- (NSUserDefaults *)userDefaults
{
    return [[NSUserDefaults alloc] initWithSuiteName:@"group.urwork.autosignin"];   //name需要是Group的id
}

来存储和读取数据,即可实现数据共享。

超微型简单方便易用数据库

假设我们需要将用户的历史搜索记录保存到本地,当接到这个需求的时候,你的脑海里可能闪过的想法:简单,本地存个字典(或者Plist文件),每个key是一个用户id,value是一个数组,数组里的每个元素是一个字典,这个字典里有articleId、title、imgUrl、...。结构大概是这样:

{
  "10086" : [
    {
      "articleId" : 1,
      "imgUrl" : "https://img.xxx.com/abcdefg.png",
      "title" : "中国历史",
      ...
    },
    {
      "articleId" : 2,
      "imgUrl" : "https://img.xxx.com/abcdefg.png",
      "title" : "中国教育",
      ...
    },
    ...
  ],
  "10087" : [
    {
      "articleId" : 2,
      "imgUrl" : "https://img.xxx.com/abcdefg.png",
      "title" : "中国教育",
      ...
    },
    ...
  ]
}

看起来OK,但是小伙伴们,性能问题还是要考虑的。我想获取某个用户的浏览历史,需要把文件整体读到内存中,然后用dict[@"10086"]的方法,得到这个用户的浏览历史Array,用户少还好,多了,每次读取的IO操作会很耗时,对性能有影响。

可能你会说用数据库啊什么的,当然可以,但是又是需要依赖一堆第三方,还要写好多代码,创建好多类。我就是想简单实现一下,有没有更好的方法呢?当然有,超微型简单方便易用数据库。

每个用户都可以用一个NSUserDefaults来代替,每个用户的浏览历史,可以直接用setObject:forKey:的方式来存储,如:

//这个跟App Groups没有关系
//已有则读取,没有则创建
NSUserDefaults *userDefaults = [[NSUserDefaults alloc] initWithSuiteName:@"10086"];
//存储
[userDefaults setObject:history forKey:@"ArticleBrowsingHistory"];
//读取
NSArray *history = [userDefaults objectForKey:@"ArticleBrowsingHistory"];

所有用户相对独立,每个用户是一个plist文件,在沙盒目录/Library/Preferences/中,

想删除也很容易,直接删除这个文件即可。
其实这个超微型简单方便易用数据库还可以实现好多功能,看你怎么操作了。如果你的App没有后台,不同用户的主题设置、语言设置可能不同,都可以通过这个来存储。

推荐阅读更多精彩内容