2017年10月20日金曜日

構造体をファイルやUserDefaultsに保存したい

ファイルやUserDefaultsには構造体を直接保存することができない。
そのため、構造体で使われてるメモリ領域を一度バイナリーデータにして(シリアライズ)、それを保存することで実現する。
(構造体の要素を辞書に変換して保存するやり方もあるんだけど、要素一個一個変換しなきゃいけなさそうなのでやったことはない)

構造体 -> Data

たとえばCGRectをDataにしてみる。

 let data = Data(bytes: &self.rect, count: MemoryLayout<CGRect>.size)

bytes:はUnsafeRawPointer。そこに変換したい変数のアドレスを渡す。
count:はその変数が使用してるメモリの大きさ。CGRectが使用するメモリの大きさはMemoryLayout<CGRect>.sizeで求められる。

要は、{アドレス}から始まる{大きさ}分のメモリをDataに直してるわけだ。

Data -> 構造体

逆にDataをCGRectに戻す。

 data.getBytes(&self.rect, length: MemoryLayout<CGRect>.size)

これも同様な引数を渡す。
dataを{アドレス}から始まる{大きさ}分のメモリに書き込んでるような感じ。
実際は書き込むというよりdataのポインタとself.rectのポインタを同じにしてんのかな? よくわからんですが。
注意なのは、このdataはSwiftのData型じゃなく、Objective-Cで使われてたNSDataということ。Dataで同じようなメソッドがあればいいんだけど、Swift4でどう書いたらいいかわからなかったので、暫定的にNSDataで書いてる。
中身がほぼ同じなんで値の扱いは困らないみたいからいいんだけど。

おそらくは
data.copyBytes(to: &self.rect, count: MemoryLayout<CGRect>.size)
のメソッドを書くんじゃないかと思うんだけど、to:に書くUnsafeRawPointerがUInt8とかで、CGRectのアドレスをどう変換したらUInt8にできるのかわかんない。
まあいずれまたわかったら追記する。

0 件のコメント:

コメントを投稿