LoginSignup
97
70

More than 3 years have passed since last update.

iOSにユーザーデータを保存する方法と、そのためのコードの書き方: UserDefaults、Core Data、Key Chain、CloudKit

Last updated at Posted at 2020-05-27

データの保存はiOSアプリの持つ主要な機能です。たとえば、ユーザーが指定した色などの環境設定を保存したり、ウェブサイトのトークンをアプリに保存したり、ToDoリストのアプリを作ってタスクを保存したりすることができます。データをシステムに保存する方法はいくつもあります。

目次

User Defaults
Core Data
Keychain
iCloud CloudKit

この記事では、上記の方法それぞれについて、サンプルコードを使って解説します。

User Defaults

主な用途

わずか2〜3行のコードで、String, Int, Bool, やどんな Data オブジェクトも保存・取り出しができます。

通常は、ユーザーがオンボーディングを終えたかどうかや、天気アプリでのユーザーのデフォルト都市等、ユーザーのプリファレンスを保存するのに使用されます。

長所

  • わずか数行のコードで簡単に実装
  • App Extensions 間でも簡単に共有
  • クラウドにデータを保存でき、ユーザーの所有デバイス間で同期可能( 同じApple ID でサインイン)

短所

シンプルなデータの保存のみに使います。データベーススキームはありません。また Apple によると、UserDefaults ストレージが512 KBに達すると警告が発せられます。そして Apple のドキュメンテーションには、ストレージが1MBに達するとアプリが終了するとあります。

Currently, there is only a size limit for data stored to local user defaults on tvOS, which posts a warning notification when user defaults storage reaches 512kB in size, and terminates apps when user defaults storage reaches 1MB in size.
https://developer.apple.com/documentation/foundation/userdefaults/1617187-sizelimitexceedednotification

しかし、Stack Overflow のユーザーの一人は、1MB以上のデータを保存してもクラッシュを起こしていないと報告しています。

https://stackoverflow.com/a/41615483

ですから、ユーザーのプリファレンスや文字列・Int値をいくらか保存したい程度であれば心配することはありません。

使い方

//To store a value
UserDefaults.standard.set("Tokyo", forKey: "currentCity")
//To read a value
let currentCity = UserDefaults.standard.string(forKey: "currentCity")

(クラウド同期バージョン)の使い方

iCloudの機能を有効にする

プロジェクト設定の Signing & Capabilities タブで、プラスボタンをクリックします。

Screen Shot 2020-05-27 at 2.23.12 PM.png

そして、iCloud 機能を追加します

Screen Shot 2020-05-27 at 2.26.28 PM.png

Key-value storage をオンにします

Screen Shot 2020-05-27 at 2.26.54 PM.png

そして、すべてのUserDefaults.standardNSUbiquitousKeyValueStore()に置き換えるだけです:

let store = NSUbiquitousKeyValueStore()
store.set("Tokyo", forKey: "currentCity")
let currentCity = store.string(forKey: "currentCity")

資源

Appleの公式文書

Core Data

主な用途

Core Data には幅広い用途があります。私の個人的な開発では、Core Data を使ってユーザーの日記、ToDoアイテム、ブックマークを保存しています。

Core Data はユーザーの情報を既存の多くのアプリに保存するために広く使われています。

長所

  • 構造化データの保存(データベーススキームを設計する必要があります)
  • 数分以内にクラウド同期サポートを有効にできる

短所

  • データベーススキームを変更するたびに、新しいデータベースバージョンを作成する必要があります。そうしないとアプリがクラッシュしてしまいます。

使い方

新しいアプリ

新しいアプリを作成する場合は、プロジェクトの作成時に Use Core Data を選択できます。

Screen Shot 2020-05-27 at 2.35.06 PM.png

既存のアプリ

また、既存のアプリに Core Data を簡単に追加できます。

最初に、データモデルファイルを作成します。キーボードのcommand-Nキーを押して、Data Model を検索します。

Screen Shot 2020-05-27 at 2.37.09 PM.png

新しい Data Model にあなたのアプリの名前をつけてください。例えば、ここでは私のアプリの名前は CoreDataDemo なので、私は CoreDataDemo.xcdatamodeld を作りました。

そして AppDelegate.swift ファイルに次の行を追加します。

// MARK: - Core Data stack

lazy var persistentContainer: NSPersistentContainer = {
    let container = NSPersistentContainer(name: "CoreDataDemo")
    container.loadPersistentStores(completionHandler: { (storeDescription, error) in
        if let error = error as NSError? {
            print(error.userInfo)
        }
    })
    return container
}()

この行で、 CoreDataDemo をあなたのアプリの名前に置き換えてください。

let container = NSPersistentContainer(name: "CoreDataDemo")

データベース構造の作成

To-Doアイテムごとに次のプロパティを格納するTo-Doアプリを作成するとします:

  • To-Doタスク名
  • タスクの担当者
  • タスクの期限
1. .xcdatamodeld ファイルを開き、Add Entity をクリックします。

Screen Shot 2020-05-27 at 2.42.46 PM.png

作成した新規エンティティ・アイテムに TodoItem という名前を付けます。

作成した新しいアイテムをダブルクリックし、名前を付けるだけです。この例では、 TodoItem という名前を付けます。

新しいプロパティを追加する

Properties セクションのプラスアイコンをクリックして、新しいプロパティを追加します。

Screen Shot 2020-05-27 at 2.44.30 PM.png

ここでは、To-Doアプリに次のプロパティが必要です。

プロパティ名 タイプ
todoTaskName String
personName String
taskDeadline Date

タイプを設定するには、プロパティ名の横にあるドロップダウンメニューをクリックします:

Screen Shot 2020-05-27 at 2.47.09 PM.png

このような感じになります。

Screen Shot 2020-05-27 at 2.48.28 PM.png

Entity クラスのコードファイルを生成
  1. 作成した新しいエンティティ項目を選択します。右側のパネルで最後のセクションのアイコンを選択します :

Screen Shot 2020-05-27 at 3.05.23 PM.png

  1. Codegen 設定を Manual/ None に変更

以前の設定:

Screen Shot 2020-05-27 at 3.08.57 PM.png

新しい設定:

Screen Shot 2020-05-27 at 3.10.38 PM.png

  1. クラス定義ファイルを生成

最上部のメニューで Editor をクリックし、Create NSManagedObject subclass... をクリックします

こうしたサブクラスを生成することで、TodoItem を新規オブジェクトの作成に直接使用できるようになります。

Screen Shot 2020-05-27 at 3.11.37 PM.png

ファイルナビゲーターに以下のファイルが表示されます :

Screen Shot 2020-05-27 at 3.13.31 PM.png

新規レコードを作成
func addNewToDoItem(todoTaskName: String, personName: String, taskDeadline: Date) {
    let appDelegate = UIApplication.shared.delegate as! AppDelegate
    let context = appDelegate.persistentContainer.viewContext
    let newItem = TodoItem(context: context)
    newItem.todoTaskName = todoTaskName
    newItem.personName = personName
    newItem.taskDeadline = taskDeadline
    do {
        try context.save()
    } catch {
        print(error.localizedDescription)
    }
}
既存のレコードを取得
func getAllPlannerDays() -> [TodoItem] {
    let appDelegate = UIApplication.shared.delegate as! AppDelegate
    let context = appDelegate.persistentContainer.viewContext
    let savedPlaceFetch = NSFetchRequest<NSFetchRequestResult>(entityName: "TodoItem")
    do {
        let result = try context.fetch(savedPlaceFetch)
        if let convertedResult = result as? [TodoItem] {
            return convertedResult
        }
    } catch {
        return []
    }
    return []
}
変更
func modifyObject(_ object: TodoItem, newDeadline: Date) {
    object.taskDeadline = newDeadline
    //保存する
    let appDelegate = UIApplication.shared.delegate as! AppDelegate
    let context = appDelegate.persistentContainer.viewContext
    do {
        try context.save()
    } catch {
        print(error.localizedDescription)
    }
}
削除
func deleteObject(_ object: NSManagedObject) {
    let appDelegate = UIApplication.shared.delegate as! AppDelegate
    let context = appDelegate.persistentContainer.viewContext
    context.delete(object)
    //保存する
    do {
        try context.save()
    } catch {
        print(error.localizedDescription)
    }
}

プログラムから TodoItem をご自身のエンティティ名に置き換えてください。

特定のレコードをクエリ中

すべての TodoItem に対し personNameネコノヒー としてクエリしましょう

func getToDoItem(withPerson: String) -> [TodoItem] {
    let appDelegate = UIApplication.shared.delegate as! AppDelegate
    let context = appDelegate.persistentContainer.viewContext
    let savedPlaceFetch = NSFetchRequest<NSFetchRequestResult>(entityName: "TodoItem")
    savedPlaceFetch.predicate = NSPredicate(format: "personName = %@", withPerson)
    do {
        let result = try context.fetch(savedPlaceFetch)
        return result as? [TodoItem]
    } catch {
        return []
    }
    return []
}

let allTodo = getToDoItem(withPerson: "ネコノヒー")

ユーザーのコアデータをクラウドに同期する

すでにここにガイドを書いています:

新しいデータベースバージョンの作成

データベースの新しいバージョン(プロパティの追加、変更、削除、または新しいエンティティの作成)を作成するたびに、データベースの新しいバージョンを作成する必要があります。

データベースモデルファイルを選択した状態で、「Editor エディター」をクリックし、「Add Model Version モデルバージョンの追加」をクリックします。

次に、ファイルナビゲーターで、データベースモデルファイルの左側にある三角形のアイコンをクリックします。

作成した新しいデータモデルバージョンをクリックします。

右側のパネルでファイルアイコンをクリックし、「Model Version モデルバージョン」を見つけて、作成した新しいモデルバージョンに切り替えます。

左側のパネルで、作成したバージョンに緑のチェックマークが付いていることを確認してください。

資源

Appleの公式文書

クラウドサポート付きCore Data

Core Dataでアプリ制作

KeyChain (キーホルダー)

主な用途

ユーザーの機密情報を保存する場合は、Key Chainに保存することをお勧めします。Keychainは、iOSがユーザーのウェブサイトのユーザー名とパスワードを保存する場所です。暗号化されており、ユーザーのパスコードまたはFace ID (Touch ID)でのみアクセスできます。

長所

  • セキュリティー
  • 保存された認証情報は、ユーザーのデバイス間で同期できます。

短所:

  • ユーザーはMac OS KeychainアプリでKeychainに保存したデータを見ることができます
  • 通常、開発者はkeychainに文字列を保存します。データを保存することはお勧めしません。

使い方

keychainにアクセスするのに必要なコードはいくつかありますが、私はkeychainに簡単にアクセスできるオープンソースのGithubリポジトリを見つけました。

資源

Appleの公式文書

CloudKit

長所

  • - データをプライベート・データベース、共有データベース、またはパブリック・データベース(すべてのユーザーが他のユーザーのレコードをフェッチできる)に保存できます。
  • CloudKitはAppleの無料クラウドサービスです。
  • CloudKitプライベート・データベースへの保存は、ユーザー自身のiCloudストレージスペースに対してカウントされます。
  • CloudKitパブリック・データベースへの保存は、割り当て制限に対してカウントされます。
  • ユーザーがアプリを削除してから再度インストールすると、CloudKitに保存されているデータをフェッチできます。

短所

  • ユーザーはオンラインである必要があります。また、CloudKitデータベースの使用にはサイズ制限があります。

実装

私は以前、「CloudKit」を使用してユーザーの情報を保存および取得する方法についてのガイドを紹介しました:

資源

Appleの公式文書

CloudKitダッシュボードの使用


:relaxed: Twitter @MszPro

:sunny: 私の公開されているQiita記事のリストをカテゴリー別にご覧いただけます。

97
70
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
97
70