前段时间 iBooks Store 还没被和谐的时候,从商店里下载一些套装书,书架上是以丛书系列的方式显示的,但是如果是自己手动添加的电子书,会发现 iBooks 并不能识别 metadata,于是网上搜索了一下相关资料,找到了一份 15 年网友给的回答1。大致情况就是:如果要自己手动添加几本书到一个 series 里,需要自己修改数据库,而且还不能通过 iCloud 同步到手机平板上去,也就是说就算手动修改成功,也只有在 macOS 上的 iBooks 有丛书显示效果。

这里大致翻译整理一下基本过程(以《来自新世界》上下册为例):

测试环境:macOS 10.12.3 (16D32)iBooks 1.8 (1261.10)

三个重要的目录:

~/Library/Containers/com.apple.iBooksX/Data/Documents/BKSeriesDatabase

~/Library/Containers/com.apple.iBooksX/Data/Documents/BKLibrary

~/Library/Containers/com.apple.BKAgentService/Data/Documents/iBooks/Books/

前两个目录里各自有一个数据库(共有 3 个文件,但是属于一个数据库),分别用于记录书籍和丛书的相关信息;第三个目录有一个 Books.plist 文件需要修改。

首先需要声明的是网上找到的那份资料在现在其实是有点问题的,后面步骤会有一些不一样。从我多次尝试的经验来看,每次启动 iBooks(准确的来讲是启动 com.apple.BKAgentService 的时候),会读取 BKSeriesDatabase 的数据,然后再读取 BKLibrary,然后对比查找看有没有新增数据,如果有就会自动生成新数据插入。

有一些步骤和之前那个资料是有区别的,并不是去修改 Books.plist,因为我发现这个文件是程序自动生成维护更新的,就算你自己修改了,每次重启 iBooks 还是会被还原回去。这里需要修改另一个数据库的数据,将书和丛书项作链接。

BKLibrary

BKLibrary 里的数据库,主要是用来记录所有存储在 iBooks 里的书籍信息。每次我们把一个 epub 添加到 iBooks 里时,程序都会自动生成一个 ID,用 ZASSETID 字段保存,这个值后面会用到。

这个数据库共有七个表:

  • ZBKCOLLECTION 用于记录精选集的信息;
  • ZBKCOLLECTIONMEMBER 用于记录精选集的成员项目;
  • ZBKJALISCOSTATUS 不清楚;
  • ZBKLIBRARYASSET 用于记录每本书的信息;
  • Z_METADATA 不清楚;
  • Z_MODELCACHE 不清楚;
  • Z_PRIMARYKEY 和上面一样,记录每个表总的行数

ZBKLIBRARYASSET

这个数据库主要修改这个表就行了,这个表里有一大堆的数据项,其实我们只需要关心其中的几个数据项:

  • ZSERIESID 自己设定的一个丛书 ID,要求不能与其他 ID 重复,这里随便设置一个值 5000
  • ZSTOREID 这个填写前面提到的 ZASSETID 值即可
ZTitle ZSERIESID ZSTOREID
来自新世界 系列 5000 5000
来自新世界(下) 5000 ZASSETID
来自新世界(上) 5000 ZASSETID

BKSeriesDatabase

BKSeriesDatabase 里的数据库总共有 4 个表,我们需要修改其中的三个表 ZBKSERIESCHECKZBKSERIESITEMZ_PRIMARYKEY

ZBKSERIESCHECK

  • Z_PK 主键;
  • Z_ENTZ_OPT 直接填 1;
  • ZDATECHECKED 日期;
  • ZADAMID 这本书或者这一系列的 ID。
Z_PK Z_ENT Z_OPT ZADAMID
10 1 1 5000
11 1 1 ZASSETID
12 1 1 ZASSETID

ZBKSERIESITEM

  • Z_PK,同样是主键,Z_ENTZ_OPT 与前一个表不太一样,直接分别填 “2” 和 “1” 就行;
  • ZISCONTAINER 用于定义当前项目是否为系列丛书项,是的话填 “1”,不是就填 “0”;
  • ZPOSITION 用于定义这本书在系列丛书里的序列(位置),注意序列从 0 开始计数。
  • ZADAMID 你懂的;
  • ZAUTHOR 系列丛书或者某本书的作者;
  • ZGENRE 系列丛书或者某本书的类别;
  • ZSEQUENCEDISPLAYNAME 定义一本书在系列里的显示名,这一项可以为空;
  • ZSERIESADAMID 系列丛书项 ID;
  • ZSERIESTITLE 系列丛书标题
  • ZSORTTITLE and ZTITLE 系列丛书或者某本书的标题
Z_PK ZADAMID ZAUTHOR ZSERIESADAMID ZSERIESTITLE ZTITLE
7 5000 貴志祐介 5000 来自新世界 系列 来自新世界 系列
8 ZASSETID 貴志祐介 5000 来自新世界 系列 来自新世界(上)
9 ZASSETID 貴志祐介 5000 来自新世界 系列 来自新世界(下)

Z_PRIMARYKEY

之后需要在这个表里修正以上两个表的行数。(重要!)

Books.plist

手动删除相关的书籍记录,因为 iBooks 会根据数据库里的信息自动生成新的 plist)(准确的说不是生成新的 plist,是在原文件的基础上增删相关信息)

全部修改完成之后,退出 iBooks,打开活动监视器,强制退出 com.apple.BKAgentService,再重启 iBooks 应该就可以了。

计划写一个小程序让 iBooks 自动识别 calibre:series 元数据添加丛书支持。

我建议苹果公司多招一些(比如像我这样的)码农把自家的软件基础功能完善一下。想把 iBooks 里的书分组到丛书栏目里还得自己手工修改数据库,而且这数据库表还设计得特别烂。??