徹底的にユーザ辞書を同期してみる
MacBookで「まーゔぇりくす=Mavericks」と登録したはずなのに、iPhoneで「まーゔぇりくす」と入力しても期待する「Mavericks」が表示されない...。いつから同期していなかったのかは不明だが、iOS7とOSX 10.9 Mavericksの環境で、ユーザ辞書が同期していないことに気付いた。
またいつものバージョンアップに伴う不具合か...と思ってしばらく放っておいたのだけど、OSX 10.9.1になっても自分のユーザ辞書は一向に同期する気配がない。どうなっているのかと検索してみると、何と!ちゃんと同期している方もいるらしい。
本当に同期するのか?こうゆうことは自分で試してみなければ気が済まない。やってみた。
-
-
- 余計な話は端折って、とにかく同期する快適なユーザー辞書にしたい方は...
- iOS7のユーザ辞書をリセットするスクリプト - ザリガニが見ていた...。
-
検証
- iCloudに接続するすべての端末で、一旦「書類とデータ」の同期をオフにした。
- その後、SafariからiCloudのWebページにログインして、
- 右上の名前のリンクから、アカウント設定 >> 詳細設定 >> 書類とデータのリセットを実行した。
- MacBookのユーザ辞書には「まーゔぇりくす=Mavericks」のみの状態にして、「書類とデータ」の同期をオン。
ゲストアカウントからiCloudに接続してみる
- ゲストアカウントにログインして、そこからiCloudにサインインしてみた。
- ユーザ辞書を確認すると、いつものアカウントで登録した「まーゔぇりくす=Mavericks」が表示されている。
- 逆に、ゲストアカウントで「れてぃな=Retina」を登録すると、いつものアカウントでも同じ辞書が確認できた。
素晴らしい!OSX環境ではちゃんと同期しているのだ。
iPhoneを工場出荷状態に戻す
- 「iPhoneを復元...」処理が進むと、二つの選択を迫られた。
- 新しいiPhoneとして設定するのか?
- 既存のバックアップから復元するのか?
- 工場出荷状態に戻したいので、新しいiPhoneとして設定してみた。
- 処理が進んで、iCloudの設定をして、待つこと暫し...
- 驚いたことに「まーゔぇりくす=Mavericks」と「れてぃな=Retina」が確認できる!
素晴らしい!工場出荷状態のiPhoneならちゃんと同期するのだ!
iPhoneを復元してみる
- なんだ、iCloudはちゃんとできる子だったんだ!と気を良くして「バックアップを復元」を実行してみた。
- するとiPhoneのユーザ辞書から「Mavericks」と「Retina」が消えた...。(ユーザ辞書には何も表示されない)
これで確信した。同期できないのは、iPhone中のファイルの問題であると。
- iCloudの「書類とデータ」の同期をオフにすると、ユーザ辞書にかなりの数の単語が表示された。
- ユーザ辞書が大き過ぎて、うまく同期できない原因になっているのかもしれない。
- そう思って、1つの単語を削除しようとすると、完了するまでに30秒以上かかる。
- ユーザ辞書の単語登録が多過ぎるためか、辞書の編集をすると、操作がやけに重い。
いつの間にか膨れ上がってしまったiPhoneのユーザ辞書が、かなり怪しい!
iPhoneのユーザ辞書はリセットできるのか?
- 工場出荷状態にすると、iPhoneのユーザ辞書はリセットされているはず。
- リセット=初期状態で何も登録がない状態。
- しかし、工場出荷状態ではその他の設定もすべてリセットされており、使い慣れたiPhoneにはほど遠い状態である。
- そこで、復元によって以前の状態に戻すのだけど、そのタイミングでユーザ辞書も多過ぎる単語で溢れてしまう...。
- ユーザ辞書を1語ずつ削除しようとしてみたが、1件30秒以上かかると、すべて削除するのはいつになるか見当もつかない...。
ユーザ辞書だけ復元したくないのだけど、脱獄しない限り、そんなことはできそうにない?
iPhoneのバックアップの中身を覗く
1つだけ思い当たる方法があった。
- モバイルデータ通信をオフにするDisable EDGE/3Gというプロファイルを削除した時の方法だ。
- その当時はまだ、モバイルデータ通信をオン・オフする設定が存在していなかった。
- iPhone / iPod Touch Backup Extractorを利用して、iPhoneのバックアップの中身を探るのだ。
- 当時プロファイルを削除した時の方法は、復元されたiOS Files中のCloudUserDictionary.sqliteのバイト数を調べて、
- 同じサイズのファイルを~/Library/Application Support/MobileSync/Backup/の中から見つけ出し、削除していた。
- 過去の成功体験から、今回も同じ方法でやってみと...
- ガーン、復元できないと警告された。
- 以前も似たような警告をされたのだけど、その時は目指すファイルがちゃんと削除れた状態で復元され、目的は達成できた。
- しかし、今回は本当に復元できていないようだ。ユーザ辞書の内容を確認してみると、以前と変わらず。同期もしない...。
iOSバージョンアップの過程で、1つでも復元できないファイルがあると、復元処理全体がキャンセルされることになってしまったのか?
バックアップの仕組みを探る
- もはやこれまでか...と思いながら、バックアップファイルの中をブラウズしていると、1つの仕組みに気付いた。
- バックアップファイルは、以下の構造になっている。
- 多数のハッシュ値のファイル
- Info.plist、Manifest.mbdb、Manifest.plist、Status.plist
$ ruby -r digest/sha1 -e 'puts Digest::SHA1.hexdigest("HomeDomain-Library/Keyboard/dynamic-text.dat")'
0b68edc697a550c9b977b77cd012fa9a0557dfcb
- バックアップを暗号化していなければ、Quick Lookで見られるファイルも多い。
- 中でもManifest.mbdbには、本の「目次」に相当する役割がありそう。
- バイナリファイルなのだけど、hexdump -Cコマンドで確認してみると、ディレクトリ情報が確認できた。
$ hexdump -C ~/Library/Application\ Support/MobileSync/Backup/fc4dd318ecd23105d1fde5b5f6c782ec4c2504e2/Manifest.mbdb | less
...(中略)...
0013f6b0 0a 48 6f 6d 65 44 6f 6d 61 69 6e 00 2f 4c 69 62 |.HomeDomain./Lib|
0013f6c0 72 61 72 79 2f 4b 65 79 62 6f 61 72 64 2f 50 68 |rary/Keyboard/Ph|
0013f6d0 72 61 73 65 4c 65 61 72 6e 69 6e 67 5f 6a 61 5f |raseLearning_ja_|
0013f6e0 4a 50 2e 64 62 2e 62 75 6e 64 6c 65 ff ff ff ff |JP.db.bundle....|
0013f6f0 ff ff 41 ed 00 00 00 00 00 00 0a 9f 00 00 01 f5 |..A.............|
0013f700 00 00 01 f5 52 e5 f6 bd 52 e5 f6 bd 52 de 02 60 |....R...R...R..`|
...(中略)...
- 目次があるのに、ページだけ削除するから、バックアップが壊れていると警告されてしまうのだ。
- 目次情報のCloudUserDictionary.sqliteを削除しておけば、警告されずに復元できるかもしれない!
しかし、Manifest.mbdbはバイナリファイルである。必要な部分だけ、1バイトも間違わずに削除するなんてことが、果たしてできるだろうか?
Manifest.mbdbを解析する
- 解析するなんて書いたが、正直、自分にはさっぱり...。
- テキスト部分はある程度予想できたが、テキストではないバイナリデータの部分は、訳が分からない。
- しかし、世の中にはすごい達人がいた。自分が行うまでもなく、.mbdbはすでに解析されていたのだ。
- つまり、バイナリデータを項目別に解析してみると、以下のように読み取れる。
0013f520 00 00 0a 48 6f 6d 65 44 6f 6d 61 69 6e 00 44 4c |...HomeDomain.DL| 0013f530 69 62 72 61 72 79 2f 4b 65 79 62 6f 61 72 64 2f |ibrary/Keyboard/| 0013f540 50 68 72 61 73 65 4c 65 61 72 6e 69 6e 67 5f 7a |PhraseLearning_z| 0013f550 68 5f 48 61 6e 74 5f 70 69 6e 79 69 6e 2e 64 62 |h_Hant_pinyin.db| 0013f560 2e 62 75 6e 64 6c 65 2f 64 61 74 61 62 61 73 65 |.bundle/database| 0013f570 2e 64 62 ff ff 00 14 01 18 48 19 51 c6 53 36 01 |.db......H.Q.S6.| 0013f580 26 1d 9e 93 79 fa 7c de e4 37 5e ff ff 81 a4 00 |&...y.|..7^.....| 0013f590 00 00 00 00 06 87 ab 00 00 01 f5 00 00 01 f5 52 |...............R| 0013f5a0 e5 f6 be 52 e5 f1 f5 52 e5 c1 bc 00 00 00 00 00 |...R...R........| 0013f5b0 00 50 00 04 00 00 0a 48 6f 6d 65 44 6f 6d 61 69 |.P.....HomeDomai| 0013f5c0 6e 00 31 4c 69 62 72 61 72 79 2f 4b 65 79 62 6f |n.1Library/Keybo| 0013f5d0 61 72 64 2f 50 68 72 61 73 65 4c 65 61 72 6e 69 |ard/PhraseLearni| 0013f5e0 6e 67 5f 7a 68 5f 48 61 6e 73 2e 64 62 2e 62 75 |ng_zh_Hans.db.bu| 0013f5f0 6e 64 6c 65 ff ff ff ff ff ff 41 ed 00 00 00 00 |ndle......A.....|
- stringは、文字数とASCIIコードで構成される、可変長のデータ。
データ種 | 項目名 | 文字数 | ASCIIコード | テキストの内容 |
---|---|---|---|---|
string | ドメイン | 00 0a | 48 6f 6d 65 44 6f 6d 61 69 6e | HomeDomain |
string | ファイルパス | 00 44 | 4c 69 62 72 61 72 79 2f 4b 65 79 62 6f 61 72 64 2f 50 68 72 61 73 65 4c 65 61 72 6e 69 6e 67 5f 7a 68 5f 48 61 6e 74 5f 70 69 6e 79 69 6e 2e 64 62 2e 62 75 6e 64 6c 65 2f 64 61 74 61 62 61 73 65 2e 64 62 |
Library/Keyboard/PhraseLearning_zh_Hant_pinyin.db.bundle/database.db |
string | シンボルのリンク先 | ff ff | ff ff=nullの意味? | |
string | データのハッシュ値 | 00 14 | 01 18 48 19 51 c6 53 36 01 26 1d 9e 93 79 fa 7c de e4 37 5e |
ファイル内容のSHA.1ハッシュ値 |
string | 不明 | ff ff | ff ff=nullの意味? |
- unitはバイト数が決められた、固定長のデータ。
データ種 | 項目名 | 内容 | 意味 |
---|---|---|---|
unit16 | モード | 81 a4 | 0100644(8xxx=ファイル、4xxx=ディレクトリ、axxx=シンボリックリンク) |
unit32 | 不明 | 00 00 00 00 | |
unit32 | 不明 | 00 06 87 ab | |
unit32 | ユーザーID | 00 00 01 f5 | 501 |
unit32 | グループID | 00 00 01 f5 | 501 |
unit32 | 日時 | 52 e5 f6 be | 2014/01/27 15:03:42(mtime) |
unit32 | 日時 | 52 e5 f1 f5 | 2014/01/27 14:43:17(atime) |
unit32 | 日時 | 52 e5 c1 bc | 2014/01/27 11:17:32(ctime) |
unit64 | ファイルサイズ | 00 00 00 00 00 00 50 00 | 20480 |
unit8 | フラッグ | 04 | |
unit8 | プロパティの数 | 00 |
$ ruby -e 'puts 0x81a4.to_s(8)' 100644 $ ruby -r time -e 'puts Time.at(0x52e5f6be).strftime("%Y/%m/%d %H:%M:%S")' 2014/01/27 15:03:42 $ ruby -r time -e 'puts Time.parse("2014/01/27 15:03:42").to_i.to_s(16)' 52e5f6be
- もし、プロパティが存在すれば、以下の「キー」と「値」のペアが「プロパティの数」だけ続くはず。
データ種 | 項目名 | バイト数 | ASCIIコード |
---|---|---|---|
string | キー | キーのバイト数 | キーの名称 |
string | 値 | 値のバイト数 | 値の内容 |
mbdbを解釈するコード
- そして、上記で解析された仕組みを実装した、mbdbを解釈するコードまで見つかった!(素晴らしい!)
- iphone - How to parse the Manifest.mbdb file in an iOS 4.0 iTunes Backup - Stack Overflow
- 自分はRubyコードで試してみた。コピーして実行すると、見事に意味のあるテキストデータに変換された!
- ところで、今回の目的はバックアップファイルから不要な設定ファイルを削除することである。
- そこで、上記ページで紹介されているコードを元に、二つの変換コードを作ってみた。
- mbdbを1レコード1行のテキストファイルに変換するコード。
- 上記テキストファイルを元にmbdbに再変換するコード。
mbdb2text.rb(mbdbをテキストに変換)
# encoding: utf-8 require 'fileutils' class ManifestParser def initialize(mbdb_filename, verbose = false) @verbose = verbose process_mbdb_file(mbdb_filename) end def to_file(filename) File.open(filename, 'w') do |f| @mbdb.each do |v| f.puts fileinfo_str(v) end end end private # Retrieve an integer (big-endian) and new offset from the current offset def getint(data, offset, intsize) value = 0 while intsize > 0 value = (value<<8) + data[offset].ord offset += 1 intsize -= 1 end return value, offset end # Retrieve a string and new offset from the current offset into the data def getstring(data, offset) return 'ffff', offset + 2 if data[offset] == 0xFF.chr and data[offset + 1] == 0xFF.chr # Blank string length, offset = getint(data, offset, 2) # 2-byte length value = data[offset...(offset + length)] value = '0000' if value == "" return value, (offset + length) end def process_mbdb_file(filename) @mbdb = Array.new data = File.open(filename, 'rb') { |f| f.read } puts "MBDB file read. Size: #{data.size}" raise 'This does not look like an MBDB file' if data[0...4] != 'mbdb' offset = 4 offset += 2 # value x05 x00, not sure what this is while offset < data.size fileinfo = Hash.new fileinfo[:start_offset] = offset fileinfo[:domain], offset = getstring(data, offset) fileinfo[:filename], offset = getstring(data, offset) fileinfo[:linktarget], offset = getstring(data, offset) fileinfo[:datahash], offset = getstring(data, offset) #fileinfo[:datahash] = fileinfo[:datahash].each_codepoint.to_a.map{|i|i.to_s(16)}.join("") if fileinfo[:datahash] != "ffff" fileinfo[:unknown1], offset = getstring(data, offset) fileinfo[:mode], offset = getint(data, offset, 2) fileinfo[:unknown2], offset = getint(data, offset, 4) fileinfo[:unknown3], offset = getint(data, offset, 4) fileinfo[:userid], offset = getint(data, offset, 4) fileinfo[:groupid], offset = getint(data, offset, 4) fileinfo[:mtime], offset = getint(data, offset, 4) fileinfo[:atime], offset = getint(data, offset, 4) fileinfo[:ctime], offset = getint(data, offset, 4) fileinfo[:filelen], offset = getint(data, offset, 8) fileinfo[:flag], offset = getint(data, offset, 1) fileinfo[:propertynum], offset = getint(data, offset, 1) fileinfo[:properties] = Hash.new (0...(fileinfo[:propertynum])).each do |ii| propname, offset = getstring(data, offset) propval, offset = getstring(data, offset) #propval = propval.each_codepoint.to_a.map{|i|i.to_s(16)}.join("") fileinfo[:properties][propname] = propval end @mbdb << fileinfo end @mbdb end def fileinfo_str(f) return "(#{f[:fileID]})#{f[:domain]}::#{f[:filename]}" unless @verbose data = [ f[:domain], f[:filename], f[:linktarget], f[:datahash], f[:unknown1], f[:mode], f[:unknown2], f[:unknown3], f[:userid], f[:groupid], f[:mtime], f[:atime], f[:ctime], f[:filelen], f[:flag], f[:propertynum], f[:properties]] #info = "%s %s %s %s %s %04x %08x %08x %08x %08x %08x %08x %08x %016x %02x %02x" % data info = data.inspect info end end if __FILE__ == $0 mp = ManifestParser.new('Manifest.mbdb', true) mp.to_file('Manifest.mbdb.txt') end
text2mbdb.rb(テキストからmbdbに変換)
# encoding: ASCII-8BIT require 'fileutils' class ManifestParser def initialize(mbdb_filename, verbose = false) @verbose = verbose process_mbdb_file(mbdb_filename) end def to_file(filename) File.open(filename, 'wb') do |f| f.write(@mbdb) end end private # Retrieve an integer (big-endian) and new offset from the current offset def getint(data, intsize) data16 = "%0#{intsize*2}x" % data [data16].pack('H*') end # Retrieve a string and new offset from the current offset into the data def getstring(str) return "\xff\xff" if str == 'ffff' return "\x00\x00" if str == '0000' return [str.length].pack('n') + str end def process_mbdb_file(filename) @mbdb = "mbdb\x05\x00" data = File.open(filename, 'rb') { |f| f.read } puts "MBDB file read. Size: #{data.size}" data.each_line do |line| #a = line.chomp.split a = eval(line) @mbdb << getstring(a[0]) @mbdb << getstring(a[1]) @mbdb << getstring(a[2]) @mbdb << getstring(a[3]) @mbdb << getstring(a[4]) @mbdb << getint(a[5], 2) @mbdb << getint(a[6], 4) @mbdb << getint(a[7], 4) @mbdb << getint(a[8], 4) @mbdb << getint(a[9], 4) @mbdb << getint(a[10], 4) @mbdb << getint(a[11], 4) @mbdb << getint(a[12], 4) @mbdb << getint(a[13], 8) @mbdb << getint(a[14], 1) @mbdb << getint(a[15], 1) a[16].each do |k, v| @mbdb << getstring(k) @mbdb << getstring(v) end end @mbdb end def fileinfo_str(f) return "(#{f[:fileID]})#{f[:domain]}::#{f[:filename]}" unless @verbose data = [ f[:domain], f[:filename], f[:linktarget], f[:datahash], f[:unknown1], f[:mode], f[:unknown2], f[:unknown3], f[:userid], f[:groupid], f[:mtime], f[:atime], f[:ctime], f[:filelen], f[:flag],f[:propertynum]] info = "%s %s %s %s %s %04x %08x %08x %08x %08x %08x %08x %08x %016x %02x %02x" % data f[:properties].each do |k, v| info += " #{k}=#{v.inspect}" end info end end if __FILE__ == $0 mp = ManifestParser.new('Manifest.mbdb.txt', true) mp.to_file('Manifest.txt.mbdb') end
実行
かなりやっつけなコードだけど、これで用が足りる。
- デスクトップにmbdb2text.rb、text2mbdb.rb、Manifest.mbdbを置いて...
- mbdb2text.rbを実行すると、テキストに変換されたManifest.mbdb.txtが生成される。
$ ruby mbdb2text.rb
- Manifest.mbdb.txtを開いて、不要なファイル情報の行を削除する。
- その後、text2mbdb.rbを実行すると、削除したファイル情報を含まないManifest.mbdb.txtが生成されるのだ。
$ ruby text2mbdb.rb
- Manifest.mbdb.txtを~/Library/Application Support/MobileSync/Backup/XXXXXXXXXXXXXX/Manifest.mbdbに移動して、準備完了。
- iTunesで「バックアップを復元...」してみる。
- 今度はエラー警告されずに、復元が完了した!
- 最初は、いくつか存在するCloudUserDictionary.sqliteファイルのみを削除しての試みだった。
- ユーザ辞書は何も登録がない状態になるのだけど、iCloudとの同期はうまく機能していないようだ。
- えーい、こうなったらLibrary/Keyboard/を含むすべてのパスを削除してしまえ!とヤケになった。
- 大丈夫、元のManifest.mbdbはちゃんとバックアップしてあるのだ。
- Manifest.mbdb.txtから、以下の行をゴソっと一気に削除してみた。
["HomeDomain", "Library/Keyboard", "ffff", "ffff", "ffff", 16832, 0, 49, 501, 501, 1390785465, 1390785465, 1390281141, 0, 4, 0, {}] ["HomeDomain", "Library/Keyboard/dynamic-text.dat", "ffff", "\n\x1F[L\xB5$\r\x9Az\x02?\x9D\xC9ja\xEB\xC1\xA2\x05\xC2", "ffff", 33152, 0, 234135, 501, 0, 1390336046, 1390336046, 1390336046, 48, 4, 0, {}] ["HomeDomain", "Library/Keyboard/PhraseLearning_zh_Hant_zhuyin.db.bundle", "ffff", "ffff", "ffff", 16877, 0, 64154, 501, 501, 1390785301, 1390785301, 1390268470, 0, 4, 0, {}] ["HomeDomain", "Library/Keyboard/PhraseLearning_zh_Hant_zhuyin.db.bundle/database.db", "ffff", "e&\xF0#3\xEA\x7F\xBDs\xD8\tn;\xBA\xE9`q\x96\x03\a", "ffff", 33188, 0, 64183, 501, 501, 1390288790, 1390284436, 1390268470, 20480, 4, 0, {}] ["HomeDomain", "Library/Keyboard/PhraseLearning_zh_Hant_pinyin.db.bundle", "ffff", "ffff", "ffff", 16877, 0, 64155, 501, 501, 1390785301, 1390785301, 1390268470, 0, 4, 0, {}] ["HomeDomain", "Library/Keyboard/PhraseLearning_zh_Hant_pinyin.db.bundle/database.db", "ffff", "\x01\x18H\x19Q\xC6S6\x01&\x1D\x9E\x93y\xFA|\xDE\xE47^", "ffff", 33188, 0, 64188, 501, 501, 1390288789, 1390284436, 1390268470, 20480, 4, 0, {}] ["HomeDomain", "Library/Keyboard/PhraseLearning_zh_Hans.db.bundle", "ffff", "ffff", "ffff", 16877, 0, 64156, 501, 501, 1390785301, 1390785301, 1390268467, 0, 4, 0, {}] ["HomeDomain", "Library/Keyboard/PhraseLearning_zh_Hans.db.bundle/database.db", "ffff", "\xD9\x19\xDA\xEA`\xFA\xD2)\xB8\x7Fj\n\xF9\xBF\xBDu\xA4{Hq", "ffff", 33188, 0, 64196, 501, 501, 1390288788, 1390284436, 1390268467, 20480, 4, 0, {}] ["HomeDomain", "Library/Keyboard/PhraseLearning_ja_JP.db.bundle", "ffff", "ffff", "ffff", 16877, 0, 2719, 501, 501, 1390785465, 1390785465, 1390281312, 0, 4, 0, {}] ["HomeDomain", "Library/Keyboard/Lexierra_ja_JP-dynamic-text.dat", "ffff", "\xDA9\xA3\xEE^kK\r2U\xBF\xEF\x95`\x18\x90\xAF\xD8\a\t", "ffff", 33152, 0, 64197, 501, 501, 1379583290, 1390284436, 1379583290, 0, 4, 0, {}] ["HomeDomain", "Library/Keyboard/CoreDataUbiquitySupport", "ffff", "ffff", "ffff", 16877, 0, 399096, 501, 501, 1390785378, 1390785378, 1390785378, 0, 4, 0, {}] ["HomeDomain", "Library/Keyboard/CoreDataUbiquitySupport/mobile~E88C661C-2206-5E67-AA19-66EC6D3EC50E", "ffff", "ffff", "ffff", 16877, 0, 399097, 501, 501, 1390785378, 1390785378, 1390785378, 0, 4, 0, {}] ["HomeDomain", "Library/Keyboard/CoreDataUbiquitySupport/mobile~E88C661C-2206-5E67-AA19-66EC6D3EC50E/UserDictionary", "ffff", "ffff", "ffff", 16877, 0, 399098, 501, 501, 1390785401, 1390785401, 1390785378, 0, 4, 0, {}] ["HomeDomain", "Library/Keyboard/CoreDataUbiquitySupport/mobile~E88C661C-2206-5E67-AA19-66EC6D3EC50E/UserDictionary/local", "ffff", "ffff", "ffff", 16877, 0, 399099, 501, 501, 1390785378, 1390785378, 1390785378, 0, 4, 0, {}] ["HomeDomain", "Library/Keyboard/CoreDataUbiquitySupport/mobile~E88C661C-2206-5E67-AA19-66EC6D3EC50E/UserDictionary/local/store", "ffff", "ffff", "ffff", 16877, 0, 399100, 501, 501, 1390785385, 1390785385, 1390785378, 0, 4, 0, {}] ["HomeDomain", "Library/Keyboard/CoreDataUbiquitySupport/mobile~E88C661C-2206-5E67-AA19-66EC6D3EC50E/UserDictionary/079F2A5D-20CE-4391-9E46-BD3C829C98CC", "ffff", "ffff", "ffff", 16877, 0, 399294, 501, 501, 1390785401, 1390785401, 1390785401, 0, 4, 0, {}] ["HomeDomain", "Library/Keyboard/CoreDataUbiquitySupport/mobile~E88C661C-2206-5E67-AA19-66EC6D3EC50E/UserDictionary/079F2A5D-20CE-4391-9E46-BD3C829C98CC/store", "ffff", "ffff", "ffff", 16877, 0, 399295, 501, 501, 1390785685, 1390785685, 1390785401, 0, 4, 0, {}] ["HomeDomain", "Library/Keyboard/BigramLearning_ja_JP.db.bundle", "ffff", "ffff", "ffff", 16877, 0, 2729, 501, 501, 1390785465, 1390785465, 1390281312, 0, 4, 0, {}] ["HomeDomain", "Library/Keyboard/.DictionaryMigrationLock.lock", "ffff", "\xDA9\xA3\xEE^kK\r2U\xBF\xEF\x95`\x18\x90\xAF\xD8\a\t", "ffff", 33188, 0, 399889, 501, 501, 1390785465, 1390785465, 1390785465, 0, 4, 0, {}] ["HomeDomain", "Library/Keyboard/CoreDataUbiquitySupport/mobile~E88C661C-2206-5E67-AA19-66EC6D3EC50E/UserDictionary/079F2A5D-20CE-4391-9E46-BD3C829C98CC/store/CloudUserDictionary.sqlite", "ffff", "\xBB>\x91\xBEF\x92B5\xD1\x0E\xDE\xF3\x90\xFF`B\x1A\xF3\x12\x89", "ffff", 33188, 0, 399297, 501, 501, 1390785685, 1390785685, 1390785401, 40960, 4, 0, {}] ["HomeDomain", "Library/Keyboard/BigramLearning_ja_JP.db.bundle/database.db", "ffff", "*\xE9k\xBB\x88\xD1\xF8\bo\xA4\x96b\xC0\xEC\x17Df\xB0\xCE\x8A", "ffff", 33188, 0, 397243, 501, 501, 1390785465, 1390785243, 1390779824, 20480, 4, 0, {}] ["HomeDomain", "Library/Keyboard/PhraseLearning_ja_JP.db.bundle/database.db", "ffff", ":\xC0\xD1\xDF\xC3/\x0FWl\xB2\x98\x04\xB9%\xB7\xF2\x1E\x96:\xBE", "ffff", 33188, 0, 397245, 501, 501, 1390785713, 1390785243, 1390782010, 20480, 4, 0, {}] ["HomeDomain", "Library/Keyboard/CoreDataUbiquitySupport/mobile~E88C661C-2206-5E67-AA19-66EC6D3EC50E/UserDictionary/local/store/CloudUserDictionary.sqlite", "ffff", "\xB8\x11F\x94k\xCC\xF6\xA4\xC7\x92\x86\xDA\xEB\xECB\x04<\xDA\xDC\x91", "ffff", 33188, 0, 399101, 501, 501, 1390785384, 1390785384, 1390785378, 49152, 4, 0, {}]
ユーザ辞書が同期するまでに試したこと
最終的にはiPhoneのLibrary/Keyboard/をリセットできたから、ユーザ辞書が正常に同期し始めたと思っているのだが、ここに辿り着くまでに、いくつもの手順を踏んでいる。それらの手順もユーザ辞書の同期を再開させるために重要かもしれないので、忘れないようにメモ。