iOS 存储方式——位运算

前言:好久不更了,怪自己懒散了,总结一个小功能算是个经验吧,有关存储方案的。
本地存储不仅考虑数据合理性,也要考虑存储压力,权衡利弊实施最适合的方案才是最重要的。

需求描述

需求图片
  • 每个开关控制着一个语音的播报
  • 开关记录存储到本地

功能实现

最简单直接的方法就是存一个model,记录每条数据的状态

{
    "voice": "rabbit",
    "status": 1
}
{
    "voice": "rabbit",
    "status": 0
}
{
    "voice": "rabbit",
    "status": 1
}
{
    "voice": "rabbit",
    "status": 0
}
{
    "voice": "rabbit",
    "status": 1
}
{
    "voice": "rabbit",
    "status": 0
}
{
    "voice": "rabbit",
    "status": 1
}

存储优化

开关状态只有「开/关」,可以想到用「0/1」标识,so灵感来了

  • 每个语音设置一个标志位
  • 每个标志位,0标识关,1标识开
声音种类 标志位 存储值
小萝卜 0b00000001 1
小白菜 0b00000010 2
小土豆 0b00000100 4
小菜椒 0b00001000 8
小南瓜 0b00010000 16
小地瓜 0b00100000 32
小白兔 0b01000000 64

对应视觉图内存储存储结果应该是

二进制 存储值
0b01000011 67

只需要存储一个【数值】,即可标志所有开关的组合,即各类组合值为 「2^N」
「0」表示所有开关关闭; 「127」表示所有开关打开

举个例子:

存储值 小萝卜 小白菜 小土豆 小菜椒 小南瓜 小地瓜 小白兔
0 0 0 0 0 0 0 0
23 0 0 1 0 1 1 1
98 1 1 0 0 0 1 0
127 1 1 1 1 1 1 1

取值设置状态(按位与)

开关状态 = 预存值 & 标志位

开关状态 = 0b 01000011(预存值) & 0b00000100(小土豆) = 0(关)

小土豆的状态

语音置开(按位或)

语音置开 = 预存值 | 标志位

语音置开 = 0b 01000011(预存值) | 0b00000100(小土豆) = 0b 01000111(新预存值=71)

小土豆打开开关

语音置关(按位异或)

语音置关 = 预存值 ^ 标志位
异或【^】:同为0、异为1

语音置关闭 = 0b 01000011(预存值) ^ 0b01000000(小白兔) = 0b 00000011(新预存值=3)

小白兔关闭开关

TODO

如果后续增加语音开关,只需要增加相关标志值即可,其他逻辑不需要修改
但枚举值必须满足「2^N」

Swift 对位运算兼容不是很友好,用十进制数字位运算也能达到效果。

总结

存储结构由一个model变成了一个数字,虽然在取值赋值操作逻辑稍微繁琐了一些,但降低了存储数据的量级,直接避免了I/O 操作,也算是特殊场景存储的最佳方案了。

蛮想念那个曾经我爱不释手的离散数学课

你可能感兴趣的:(iOS 存储方式——位运算)