[iOS]「データベース」

Swiftで使えるデータベースを迷っていませんか?

この記事を読むことで、Swiftで利用できるデータベースの選び方と基本的な使用方法を理解できます。

データベースは、代表的な「Userdefaults」、「Keychain」、「SQLite」、「CoreData」、「Realm」について解説します。

目次

データベースの紹介と選び方

データベースは、アプリケーション内でデータを効率的に管理するための仕組みです。
データベースを使うことで、データの永続性を確保し、アプリケーションのパフォーマンスを向上させることができます。また、複雑なデータ操作やクエリの実行も容易になります。

データベースの選び方

Swift言語で使えるデータベースの種類や選び方のポイントについて解説します。

それぞれのポイントごとに、おすすめのデータベースの順位づけをしましたので、参考にしてください。

ポイント1:簡単な使い方

初心者にとっては、簡単に使えるデータベースが重要です。使いやすいAPIや直感的な操作インターフェースを持つデータベースを選ぶことがおすすめです。

Userdefaults:

  • Userdefaultsは非常に簡単に使えるデータベースです。
  • その名前の通り、キーバリューストア型のデータ保存を容易に行うことができます。

Realm:

  • Realmはモダンなモバイルデータベースであり、直感的なAPIとシームレスな統合性が特徴です。

Core Data:

  • Core DataはXcodeのフレームワークであり、Swift言語との統合が優れています。

SQLite:

  • SQLiteは広く使われている軽量なリレーショナルデータベースです。

Keychain:

  • Keychainはデータのセキュリティを重視する場合に適しています。
  • 初心者にとっては操作がやや複雑な部分もありますが、セキュアなデータ保存が必要な場合には重要な選択肢となります。
ポイント2:データベースのタイプ

データベースの種類には、軽量なデータ保存に適したキーバリューストア型のデータベースや、リレーショナルデータベースなどがあります。アプリの要件に合ったタイプを選ぶことが重要です。

キーバリューストア型データベースは、キーと値のペアを使ってデータを格納するデータベースのタイプです。

キーバリューストア型データベース

Userdefaults:

  • シンプルなデータの保存と読み込みに適しています。

リレーショナルデータベースは、データを複数のテーブルに分割し、それらのテーブル間の関係性を定義してデータを管理するデータベースのタイプです。

リレーショナルデータベース

Core Data:

  • リレーショナルデータベースとしての機能だけでなく、オブジェクト指向のデータ管理を提供します。

SQLite:

  • 軽量なリレーショナルデータベースであり、データの永続化や複雑なデータ操作に適しています。
その他のデータベース

Keychain:

  • セキュリティに特化したデータベースであり、機密情報の保存に適しています。

Realm:

  • モダンなモバイルデータベースであり、高速な処理とリアルタイムデータ同期機能を提供します。
ポイント3:パフォーマンス

アプリのパフォーマンスは重要な要素です。データベースの高速な読み書き操作やクエリの効率性を考慮しましょう。特に大量のデータを処理する場合には、パフォーマンスがより重要となります。

Realm:

  • Realmはモバイル向けに最適化されたデータベースであり、高速な読み書き性能を提供します
  • 簡単な操作インターフェースやシンプルなデータモデルが初心者にも使いやすく、リアルタイムデータ同期や暗号化などの機能も備えています

Core Data:

  • Core DataはAppleが提供するフレームワークであり、iOSアプリ開発において幅広く使用されています。
  • パフォーマンスが高く、高度な機能やデータモデルの管理をサポートしています

SQLite:

  • SQLiteは高速で軽量なリレーショナルデータベースです。

Userdefaults:

  • 小規模なデータの保存に適しており、簡単にデータを永続化できます。
  • しかし、大量のデータや複雑なデータモデルの管理には向いていません

Keychain:

  • パスワードやトークンなどの機密情報を安全に保存するために使用されます。
  • パフォーマンスは他のデータベースに比べて低めですが、セキュリティが最重要視される場合には適しています。
ポイント4:拡張性と柔軟性

アプリの成長に合わせてデータベースを拡張できるかどうかも重要な要素です。柔軟なスキーマ変更やデータモデルの拡張が容易なデータベースを選ぶことが望ましいです。

Realm:

  • Realmはモバイル向けに設計された柔軟性と拡張性に優れたデータベースです。
  • アプリの成長に対応しやすく、柔軟な開発が可能です。

Core Data:

  • Core Dataは柔軟なデータモデルの管理が可能なフレームワークです。
  • データモデルの拡張や関連性の追加が容易であり、アプリの拡張性に対応することができます。

SQLite:

  • SQLiteは柔軟性と拡張性に優れたリレーショナルデータベースです。
  • スキーマの変更やデータモデルの拡張が比較的容易であり、アプリの成長に合わせて柔軟に対応することができます。

Userdefaults:

  • Userdefaultsは小規模なデータの保存に適していますが、拡張性には限界があります

Keychain:

  • Keychainはセキュリティに特化したデータ保存に適していますが、拡張性には制約があります

おすすめのデータベースはこれ!

これまで、データベースの選び方のポイントについて解説してきましたが、総合的に判断しておすすめなデータベースを紹介したいと思います。使用環境や使用用途により結果は異なりますのでご注意ください。

おすすめ1:Realm
  • モバイルアプリ向けに特化したデータベースであり、高速なデータアクセスやリアルタイム同期機能を提供しています。
  • 簡潔なAPIやオブジェクト指向的なデータモデリングにより、開発者が直感的に操作できます。
おすすめ2:Core Data
  • Xcodeとのシームレスな統合や豊富な機能セットがあり、iOSアプリ開発において幅広く使われています。
  • オブジェクトグラフの管理やデータの永続化に優れており、複雑なデータモデルの管理も容易です。

各種データーベースの基本的な使用方法

Userdefaults

Userdefaultsを利用して、データを簡単に保存・読み込みする方法の概要を紹介します。

初心者の方でも迷うことなく使えるように、具体的な手順をわかりやすく解説した記事がありますのでこちらも参照ください。Userdefaults該当ページはこちら

Userdefaultsは、小規模なデータをシンプルに永続化するための手段として広く使われています。例えば、ユーザーの設定値やアプリ内の状態情報を保存したい場合に便利です。

データの保存方法

まず、データの保存方法です。以下のコードを使用して、Userdefaultsにデータを保存することができます。

Userdefaults:データの保存方法
let defaults = UserDefaults.standard
defaults.set("保存したいデータ", forKey: "キー")
  • UserDefaults.standardを使ってUserdefaultsのインスタンスを取得しています。
  • set(_:forKey:)メソッドを使用してデータを保存しています。
  • 保存するデータは、”保存したいデータ“という文字列です。
  • キー“という識別子を指定してデータを識別します。

Userdefaultsを使って保存できるデータの種類には制約があります。主に以下のデータ型が利用可能です。

Userdefaultsを使って保存できるデータの種類
  • String: 文字列
  • Int, Float, Double: 数値
  • Bool: 真偽値
  • Data: バイナリデータ
  • Date: 日付

データを読み込む方法

次に、保存したデータを読み込む方法です。以下のコードを使用して、Userdefaultsからデータを読み込むことができます。

Userdefaults:データを読み込む方法
let defaults = UserDefaults.standard
if let savedData 
    = defaults.object(forKey: "キー") as? String {
    // データの読み込みが成功した場合の処理
    print(savedData)
} else {
    // データの読み込みが失敗した場合の処理
    print("データが存在しません")
}
  • object(forKey:)メソッドを使用して指定した”キー“に対応するデータを読み込んでいます。
  • 読み込んだデータはオプショナル型で返されるため、if letを使ってアンラップして利用します。
  • 成功した場合は、保存されたデータが取得できます。
  • 失敗した場合は、データが存在しないことを示すメッセージが表示されます。

データを削除する方法

Userdefaultsでは、保存したデータを不要になったときに削除することができます。データの削除方法を具体的なコード例を交えて解説します。

Userdefaults:データを削除する方法
// Userdefaultsからデータを削除する
UserDefaults.standard.removeObject(forKey: "key")

上記のコードでは、"key"というキーに対応するデータをUserdefaultsから削除しています。これにより、不要なデータを効率的に削除することができます。

このように、Userdefaultsを使ってデータの保存、読み込み、削除などを行うことができます。

ただし、大容量のデータや複雑な構造を持つデータの保存には、他のデータベースオプションを検討することをおすすめします。

Keychain

セキュリティに重要なKeychainを使用したデータ保存方法について解説します。Keychainの基本的な使い方や注意点を具体的なコード事例を交えて詳しく説明します。

Keychainは、iOSアプリケーションでのセキュアなデータの保存に使用される領域です。主にユーザーのパスワードやトークン、秘密鍵などの機密情報を安全に保存するために活用されます。

データの保存方法

まず、Keychainを使ったデータの保存方法です。以下のコードを使用して、Keychainにデータを保存する手順を示します。

Keychainデータの保存方法
import Security

let serviceName = "com.example.myApp"
let accountName = "user@example.com"
let password = "secretpassword"

let query: [String: Any] = [
    kSecClass as String: kSecClassInternetPassword,
    kSecAttrService as String: serviceName,
    kSecAttrAccount as String: accountName,
    kSecValueData as String: password.data(using: .utf8)!
]

let status = SecItemAdd(query as CFDictionary, nil)
if status == errSecSuccess {
    print("データの保存に成功しました")
} else {
    print("データの保存に失敗しました")
}
  • import Security:
    Securityフレームワークをインポートしています。Keychainを操作するために必要なフレームワークです。
  • let serviceName = "com.example.myapp":
    Keychainに保存するデータの識別子として使用されるサービス名を定義しています。一意な名前を付けることで、他のアプリとの衝突を避けます。
  • let accountName = "user@example.com":
    アカウント名を定義しています。ユーザーを特定するための情報として使用されます。
  • let password = "secretpassword":
    保存したいデータ(パスワードなど)を定義しています。
  • let query: [String: Any] = [...]:
    Keychainへのデータ保存に関するクエリを定義しています。クエリは辞書形式で指定されており、保存するデータの種類やサービス名、アカウント名、保存したいデータ自体を指定しています。
  • let status = SecItemAdd(query as CFDictionary, nil):
    定義したクエリを使用して、データをKeychainに保存しています。SecItemAdd関数はKeychainにデータを追加するメソッドで、返り値としてステータスを取得しています。
  • if status == errSecSuccess { ... } else { ... }:
    status変数の値をチェックして、データの保存が成功したかどうかを判定しています。errSecSuccessはデータの保存が成功したことを示す定数です。

データを取得する方法

次に、保存したデータを取得する方法です。以下のコードを使って、Keychainからデータを取得できます。

Keychainデータを取得する方法
let query: [String: Any] = [
    kSecClass as String: kSecClassInternetPassword,
    kSecAttrService as String: serviceName,
    kSecAttrAccount as String: accountName,
    kSecMatchLimit as String: kSecMatchLimitOne,
    kSecReturnData as String: true
]

var item: CFTypeRef?
let status = SecItemCopyMatching(query as CFDictionary, &item)

if status == errSecSuccess, let retrievedData = item as? Data,
   let retrievedPassword = String(data: retrievedData, encoding: .utf8) {
    print("取得したデータ: \(retrievedPassword)")
} else {
    print("データの取得に失敗しました")
}
  • let query: [String: Any] = [...]:
    Keychainからデータを取得するためのクエリを定義しています。クエリは辞書形式で指定されており、取得したいデータの種類やサービス名、アカウント名などを指定しています。
  • var item: CFTypeRef?:
    取得したデータを格納する変数を宣言しています。この変数はSecItemCopyMatching関数の第2引数として使用されます。
  • let status = SecItemCopyMatching(query as CFDictionary, &item):
    定義したクエリを使用して、Keychainからデータを取得しています。
    SecItemCopyMatching関数はKeychainからデータを取得するメソッドで、返り値としてステータスを取得しています。
  • if status == errSecSuccess, let retrievedData = item as? Data, let retrievedPassword = String(data: retrievedData, encoding: .utf8) { ... } else { ... }:
    取得したデータが正常にある場合、データを解読して表示しています。取得したデータはData型であるため、String型に変換してパスワードなどを取り出しています。
  • print("取得したデータ: \(retrievedPassword)"):
    成功した場合は、取得したデータを表示しています。
  • print("データの取得に失敗しました"):
    失敗した場合は、エラーメッセージを表示しています。

セキュリティに関する注意点

Keychainの利用においては、セキュリティに関する注意点も重要です。以下の点に留意することが推奨されます。

Keychain:セキュリティに関する注意点
  1. データの暗号化:
    データを保存する際には、必要に応じて適切な暗号化手法を使用してデータを保護します。
  2. キーチェーンアクセスグループ:
    アプリ内で複数のグループでデータを共有する場合、キーチェーンアクセスグループを設定することで適切なアクセス制御を行います。
  3. パスワードの管理:
    パスワードなどの機密情報を扱う場合には、安全な方法で管理する必要があります。

SQLite

SQLiteデータベースの基本的な概念と、iOSアプリでの利用法について解説します。

SQLiteは、シンプルで軽量なデータベースエンジンであり、iOSアプリケーションでのデータの永続化やクエリの実行に広く使用されています。

データベースの作成とテーブルの作成方法

以下のコードを使用して、SQLiteデータベースを作成し、テーブルを作成する手順を示します。

SQLiteデータベースの作成とテーブルの作成方法
import SQLite

let db = try Connection("path/to/database.sqlite")
let users = Table("users")
let id = Expression<Int>("id")
let name = Expression<String>("name")
let age = Expression<Int>("age")

try db.run(users.create { table in
    table.column(id, primaryKey: true)
    table.column(name)
    table.column(age)
})
  • import SQLite:
    SQLiteライブラリをインポートしています。これにより、Swift言語でSQLiteデータベースを操作する機能が使用できるようになります。
  • let db = try Connection("path/to/database.sqlite"):
    SQLiteデータベースへの接続を確立しています。引数にはデータベースファイルのパスを指定しています。データベースファイルが存在しない場合は新しく作成されます。
  • let users = Table("users"):
    テーブルを定義しています。テーブル名はusersとしました。
  • let id = Expression<Int>("id"):
    カラムを定義しています。Expressionを使用して、カラムの名前とデータ型を指定しています。この例では、idカラムは整数型(Int)として定義しています。
  • let name = Expression<String>("name"):
    別のカラムnameを定義しています。こちらは文字列型(String)として定義しています。
  • let age = Expression<Int>("age"):
    最後に、ageカラムを定義しています。こちらも整数型(Int)として定義しています。
  • try db.run(users.create { table in ... }):
    テーブルを作成するための処理を行っています。db.runメソッドにusers.createクロージャを渡しています。このクロージャの中でテーブルのカラムを定義しています。
    • table.column(id, primaryKey: true):
      テーブルにidカラムを追加しています。primaryKey: trueとすることで、idカラムをプライマリーキーとして設定しています。プライマリーキーはテーブル内の各レコードを一意に識別するための特別なカラムです。
    • table.column(name):
      テーブルにnameカラムを追加しています。
    • table.column(age):
      テーブルにageカラムを追加しています。

これにより、SQLiteデータベースにusersテーブルが作成され、テーブル内にはidnameageの3つのカラムが定義されます。このようにSQLiteを使用することで、データベースとテーブルを簡単に作成できます。データベース操作には他にも、データの挿入、更新、削除、クエリなどの機能があります。必要に応じてこれらの機能を活用して、データの管理を行いましょう。

データの挿入とクエリの実行

次に、以下のコードを使用して、データの挿入クエリの実行を行う手順を示します。

SQLiteデータの挿入とクエリの実行
let insert = 
    users.insert(name <- "John", age <- 25)

try db.run(insert)

for user in try db.prepare(users) {
    print("ID: \(user[id]), 
           Name: \(user[name]), 
           Age: \(user[age])")
}
  1. let insert = users.insert(name <- "John", age <- 25):
    データを挿入するためのクエリを定義しています。
    usersテーブルにnameカラムに”John”という文字列を、ageカラムに25という整数を挿入するクエリを定義しています。
    users.insertメソッドは、新しいレコードを作成するためのクエリを生成します。
  2. try db.run(insert):
    定義したクエリを使用して、データベースにデータを挿入しています。
    db.runメソッドは、クエリを実行するためのメソッドで、データベースにデータを追加することができます。tryキーワードを使っているため、何らかのエラーが発生する可能性がある場合はエラーハンドリングが行われます。
  3. for user in try db.prepare(users) { ... }:
    usersテーブル内のデータを取得しています。
    db.prepareメソッドは、指定したテーブルのすべてのデータを取得するためのメソッドです。
  4. print("ID: \(user[id]), Name: \(user[name]), Age: \(user[age])"):
    データベース内の各レコードを取り出し、IDNameAgeのカラムの値を表示しています。
    各レコードのカラムには、user[id]のようにアクセスします。

上記のコードは、SQLiteデータベースにデータを挿入し、その後データベース内のデータを取得して表示する基本的な手順を示しています。データベース操作には他にも、データの更新、削除、クエリなどの機能があります。

Core Data

Core Dataフレームワークを使ったデータモデルの設計と基本的な使い方について説明します。

初心者の方でも迷うことなく使えるように、具体的な手順をわかりやすく解説した記事がありますのでこちらも参照ください。CoreData該当ページはこちら

Core Dataは、iOSアプリケーションでのデータの永続化と管理に使用されるフレームワークです。

Core Dataフレームワークの基本的な使い方を紹介します。以下のコードを使用して、Core Dataを初期化し、データの保存と取得を行う手順を示します。

Core Dataスタックの初期化

Core DataCore Dataスタックの初期化
import CoreData

// Core Dataスタックの初期化
lazy var persistentContainer: NSPersistentContainer = {
    let container = NSPersistentContainer(name: "DataModel")
    container.loadPersistentStores { _, error in
        if let error = error {
            fatalError("データベースの初期化に失敗しました: \(error)")
        }
    }
    return container
}()
  1. import CoreData:
    Core Dataフレームワークをインポートしています。これにより、Core Dataを使用するための機能が利用できるようになります。
  2. lazy var persistentContainer: NSPersistentContainer = { ... }():
    Core Dataスタックの初期化を行っています。
    NSPersistentContainerクラスは、Core Dataスタックを管理するためのクラスです。
    Core Dataスタックはデータベースの初期化や永続化を行うための重要な要素です。
    lazy varを使って遅延初期化されるため、実際にデータを使用するまで初期化が遅延されます
  3. container.loadPersistentStores { _, error in ... }:
    データベースの初期化を行っています。
    loadPersistentStoresメソッドは、永続ストアをロードしてCore Dataスタックを初期化するためのメソッドです。
    エラーが発生した場合は、初期化が失敗したと判断してエラーメッセージを表示しています。

データの保存

Core Dataデータの保存
import CoreData

// データの保存
func saveData() {
    let context = persistentContainer.viewContext

    do {
        try context.save()
        print("データが保存されました")
    } catch {
        print("データの保存に失敗しました: \(error)")
    }
}

func saveData() { ... }:

  1. データを保存するメソッドを定義しています。
  2. Core DataスタックからviewContextを取得し、データを保存しています。
  3. context.save()メソッドを使って、変更されたデータを永続化することができます。
  4. 保存に成功した場合は「データが保存されました」と表示されます。
  5. 保存に失敗した場合は、エラーメッセージが表示されます。

データの取得

Core Dataデータの取得
import CoreData

// データの取得
func fetchData() {
    let context = persistentContainer.viewContext
    let request: NSFetchRequest<Entity> = Entity.fetchRequest()

    do {
        let entities = try context.fetch(request)
        for entity in entities {
            print("属性A: \(entity.attributeA), 属性B: \(entity.attributeB)")
        }
    } catch {
        print("データの取得に失敗しました: \(error)")
    }
}

func fetchData() { ... }:

  • データを取得するメソッドを定義しています。
  • Core DataスタックからviewContextを取得し、NSFetchRequestを使用してデータを取得しています。
  • 取得したデータはforループを使って一つずつ取り出し、「属性A」と「属性B」の値を表示しています。
  • データの取得に失敗した場合は、エラーメッセージが表示されます。

以上の手法を使うことで、Core Dataフレームワークの使い方とデータモデルの設計手法を学ぶことができます。Core Dataを活用してデータを管理し、アプリケーションの開発を効率化しましょう。

Realm

モダンなデータベース解決策であるRealmの導入と基本的な操作方法について解説します。

初心者の方でも迷うことなく使えるように、具体的な手順をわかりやすく解説した記事がありますのでこちらも参照ください。

Realmは、モバイルアプリケーション向けの高速で柔軟なデータベースです。

Realmの基本的な操作方法を紹介します。以下のコードを使用して、Realmデータベースの作成、データの追加、データの取得などの基本的な操作を行います。

データベースの作成

Realmデータベースの作成
import RealmSwift

// Realmデータベースの作成
let realm = try! Realm()

// モデルクラスの定義
class Person: Object {
    @Persisted var name: String = ""
    @Persisted var age: Int = 0
}
  1. import RealmSwift:
    RealmSwiftフレームワークをインポートしています。
    これにより、Realmを使用するための機能が利用できるようになります。
  2. let realm = try! Realm():
    Realmデータベースを作成しています。try!を使用しているため、データベースの作成に失敗した場合は実行時エラーとなります。
  3. class Person: Object { ... }:
    データベース内のテーブルに相当するモデルクラスを定義しています。
    Objectクラスを継承したPersonクラスがモデルとなります。
    @Persisted属性を使って各カラムを定義しています。
@Persisted属性

Realmはオブジェクト指向データベースであり、データモデルをSwiftのクラスとして表現します。このクラスのプロパティ(カラム)に@Persisted属性を付与することで、そのプロパティはデータベース内で永続化されることを意味します。

このPersonクラスは、Realmデータベース内にnameageという2つのカラムを持つテーブルに相当します。@Persisted属性がついているため、このクラスのインスタンスのnameageプロパティに値を設定すると、その値がデータベースに永続的に保存されます。

データの追加

Realmデータの追加
import RealmSwift

// データの追加
let person = Person()
person.name = "John"
person.age = 25

try! realm.write {
    realm.add(person)
}
  1. let person = Person():
    データベースに追加する新しいPersonオブジェクトを作成しています。
  2. person.name = "John"person.age = 25:
    Personオブジェクトのnameageプロパティに値を設定しています。
  3. try! realm.write { ... }: データの追加を行っています。
    realm.writeブロック内でデータベースの更新を行うことができます。
    realm.add(person)Personオブジェクトをデータベースに追加しています。

データの取得

Realmデータの取得
import RealmSwift

// データの取得
let people = realm.objects(Person.self)
for person in people {
    print("Name: \(person.name), Age: \(person.age)")
}
  • let people = realm.objects(Person.self):
    データの取得を行っています。
    realm.objectsメソッドは、指定した型のオブジェクトをすべて取得するためのメソッドです。この例では、Personクラスのオブジェクトをすべて取得しています。
  • for person in people { ... }:
    取得したデータをforループを使って一つずつ取り出しています。
    personオブジェクトのnameageプロパティを表示しています。

以上の手法を使うことで、Realmの導入と基本的な操作方法を学ぶことができます。Realmを使ってモダンなデータベース解決策を実現し、柔軟で高速なデータの管理を行いましょう。

この記事が気に入ったら
いいね または フォローしてね!

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!

コメント

コメントする

目次