CoreDataの勉強のため、Swiftで簡単なTodoアプリを作ってみた。
仕様について、UIはSwiftUIで一画面のビューを実装し、データの保存にCoreDataを使う。
それでは早速実装したコードを紹介しながら、各コードでどのような処理をしているかを解説していく。
コンテンツ
コード全文
まず、コード全文を載せておく。
01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 | import SwiftUI import CoreData struct ContentView : View { @FetchRequest ( sortDescriptors: [ NSSortDescriptor (keyPath: \ Task .name, ascending: false )], animation: . default ) var tasks: FetchedResults < Task > @Environment (\.managedObjectContext) var viewContext @State var new = "" var body: some View { VStack { HStack { TextField ( "Input here" , text: $ new ) .textFieldStyle( RoundedBorderTextFieldStyle ()) Button (action: { let newTask = Task (context: self .viewContext) newTask.name = self . new do { try self .viewContext.save() } catch { let nsError = error as NSError fatalError( "Unresolved error \(nsError), \(nsError.userInfo)" ) } self . new = "" }) { Text ( "追加" ) } } List { ForEach (tasks, id: \. self ) { task in Text ( "\(task.name!)" ) } } }.padding() } } |
なお、プロジェクト作成時には「Use Core Data」へチェックを入れておくことが前提だ。
また、事前に下記のとおりエンティティを定義しておく。

CoreDataからデータを取得する
CoreDataからデータを取得するには、簡単にデータを取り出せるようFetchRequestプロパティラッパー(コード5行目)が定義されている。
FetchRequestは、DynamicPropertyプロトコルを採用しているので、関連するビューのプロパティも自動更新してくれるようになっている。
1 2 3 4 | @FetchRequest ( sortDescriptors: [ NSSortDescriptor (keyPath: \ Task .name, ascending: false )], animation: . default ) |
今回の取得条件は、sortDescriptorsでTask.nameをキーとして降順(新しいタスクが上)でフェッチするように指定している。
フェッチした結果はFetchResults型として返されるので、以下のようにして取得する。
1 | var tasks: FetchedResults < Task > |
データベース操作で必要なコード
CoreDataを使ったデータベース操作にはNSManagedObjectContextのインスタンスが必要になるので、以下でインスタンスを取得する。(11行目)
1 | @Environment (\.managedObjectContext) var viewContext |
タスク追加用のフィールドとボタンを用意する
ここからはビューの実装が絡んでくる。(12行目以降)
まず、タスク名を入力するTextFieldを用意し、状態変数newをバインドさせておく。(17行目)
1 2 | TextField ( "Input here" , text: $ new ) .textFieldStyle( RoundedBorderTextFieldStyle ()) |
19行目でタスク追加ボタンのビューを用意しているが、このとき20行目からCoreDataへのデータ追加処理をおこなっている。
1 2 | let newTask = Task (context: self .viewContext) newTask.name = self . new |
まずTaskクラスのインスタンスであるnewTaskを生成し、name属性に入力した値self.newを設定している。
このときTaskクラスのイニシャライザには、ManagedObjectContextを渡す必要がある。
そして22行目からデータベースへの保存処理をおこなっていく。
1 2 3 4 5 6 | do { try self .viewContext.save() } catch { let nsError = error as NSError fatalError( "Unresolved error \(nsError), \(nsError.userInfo)" ) } |
saveメソッドはエラーを返す可能性があるので、必ずtry/catch文を使った例外処理を書いておく必要がある。
取得したデータの一覧表示
ここまで、CoreDataを使ってデータベースにデータを追加する処理を書いてきたが、次はCoreDataから取得してきたデータをListビューに一覧表示する処理を書いていく。
1 2 3 4 5 | List { ForEach (tasks, id: \. self ) { task in Text ( "\(task.name!)" ) } } |
35行目でListビューを定義しており、ForEach文を使ってあらかじめ取得しておいたtasksを出力している。
Todoアプリの完成
完成したアプリをビルドした結果がこちら。
追加したタスクはリストにどんどんスタックされていき、アプリをいったん落とし再起動しても、追加したタスクが残っている。

この簡易Todoアプリをベースに少しずつ改良を加え、CoreDataへの理解を深めていこうと思う。