[Swift 4][OSS] struct、image、dataを簡単にファイルへ永続化できる?「Disk」を試してみた

2017.08.25

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

? Diskとは

リポジトリから引用します。

Delightful framework for iOS to easily persist structs, images, and data

struct、image、dataを簡単に永続化するためのiOS用のフレームワークとのこと。
MITライセンスで公開されています。 今回はこのDiskを試してみました。

検証環境

本記事は以下の環境で検証を行っています。

  • macOS Sierra バージョン 10.12.6
  • Xcode Version 9.0 beta 6 (9M214v)
  • Swift 4
  • iPhone 7 Plus シミュレーター iOS 11.0
  • CocoaPods 1.3.1

README.mdに以下の記載があります。

Disk uses the new Codable protocol introduced in Swift 4 to its utmost advantage and gives you the power to persist structs without ever having to worry about encoding/decoding.

Swift 4から使えるCodableプロトコルを使っているということでXcode 9(記事執筆時点ではベータ版)を使う必要があります。
また、CompatibilityによるとiOS 9以上が必要とのことです。

本記事は ベータ版のXcode 9を使用して検証を行っています。そのため、正式版がリリースされた際にはライブラリの使用方法等が変わる可能性があります。ご留意の上、お読みください。

セットアップ方法

Carthageにも対応していますが、今回はCocoaPodsでインストールします。 Podfileに以下を記載し、pod installします。

target 'DiskSample' do
  use_frameworks!
  pod 'Disk'
end

記事執筆時点でバージョン0.2.1がインストールされました。インストール後は.xcworkspaceファイルを開けばDiskが使える状態になります。

使ってみる

Diskは記事執筆時点で以下のデータ型のファイルへの永続化をサポートしています。
特徴はなんといってもCodableプロトコルをサポートしていることではないでしょうか!?

  • Codable
  • [Codable]
  • UIImage
  • [UIImage]
  • Data
  • [Data]

Codableを保存する

まずは以下のようにCodableに準拠したstructを定義します。

struct User: Codable {
    let id: Int
    let name: String?
}

このstructを保存してみます。 保存先はDocumentsディレクトリにしていますが、他にもcachestemporaryが指定できます。

let user1 = User(id: 1, name: "Kato")
let user2 = User(id: 2, name: nil)

try? Disk.save(user1, to: .documents, as: "user1.json")
try? Disk.save(user2, to: .documents, as: "user2.json")

実行してディレクトリを覗いてみるとちゃんとjsonファイルが保存されていました。

save_to_documents

ファイルをテキストエディタで開くとこんな感じ。

user1.json

{"id":1,"name":"Kato"}

user2.json

{"id":2}

たった1行で保存できて便利ですね。

保存したCodableを読み込む

保存ができたので読み込んでみます。読み込むのも簡単です。

// User.selfを指定することで結果をUser型として受け取れる
if let user1 = try? Disk.retrieve("user1.json", from: .documents, as: User.self) {
    print(user1) // User(id: 1, name: Optional("Kato"))
}
if let user2 = try? Disk.retrieve("user2.json", from: .documents, as: User.self) {
    print(user2) // User(id: 2, name: nil)
}

保存時にサブディレクトリを作成する

保存時にディレクトリのパスを含むようにすれば自動でディレクトリを作成してくれます。 以下のように階層が深くても大丈夫。

// Documentsディレクトリにサブディレクトリを作成して保存する
try? Disk.save(user1, to: .documents, as: "directory1/directory1_1/user1.json")

save_to_nested_directory

Data型を保存・読み込む

以下のようにしてData型を保存・読み込みます。

// 保存
let data = "データだよ".data(using: .utf8)!
try? Disk.save(data, to: .documents, as: "data")

// 読み込み
if let retrievedData = try? Disk.retrieve("data", from: .documents, as: Data.self) {
    print(String(data: retrievedData, encoding: String.Encoding.utf8)!) // データだよ
}

ちゃんと保存されてますね。

save_data

UIImageを保存・読み込む

以下のようにUIColorとCGSizeを指定してUIImageを生成する関数を用意しました。

/// UIColorとCGSizeを指定してUIImageを生成する。
///
/// - Parameters:
///   - color: 色
///   - size: サイズ
/// - Returns: UIImage
func image(color: UIColor, size: CGSize) -> UIImage {
    let renderer = UIGraphicsImageRenderer(size: size)
    return renderer.image { ctx in
        ctx.cgContext.setFillColor(color.cgColor)
        ctx.fill(CGRect(origin: .zero, size: size))
    }
}

上記の関数を使用してUIImageの保存・読み込みを行ってみました。

// UIImageを生成
let myImage = image(color: .red, size: CGSize(width: 100, height: 100))

// 保存
try? Disk.save(myImage, to: .documents, as: "myImage")

// 読み込み
if let myImage = try? Disk.retrieve("myImage", from: .documents, as: UIImage.self) {
    print(myImage) // <UIImage: 0x6040000b6800>, {300, 300}
}

こちらもちゃんと保存されてます。 save_image

おわりに

今回はstruct、image、dataを簡単にファイルに永続化できるDiskを試してみました。本当に簡単に使えますね! なお、本記事ではサンプルなのでエラーハンドリングをtry?try!で済ませてしまっていますが必要に応じてちゃんとエラーをcatchしてエラー処理するようにしてください。