概要
CoreDataを使って以下のような関係を作りました。
User : Task = 1 : n
あるユーザーに属するタスクの一覧を取得するときは user.tasks
みたいな感じで取得できると思ってたのですが、取得できませんでした。
今回の記事でユーザーに属するタスクを取得して画面に表示する方法を紹介します。
環境
macOS Monterey 12.1
Xcode 13.2.1
手順
- CoreDataを使って
User : Task = 1 : n
を表現する(記事の主題から外れるため詳しい説明は割愛) - ユーザーに属するタスクの一覧を取得する
- 取得したタスクの一覧を画面に表示する
1. User : Task = 1 : n
を表現する
↑こちらの記事を参考にしました。
コードは以下です。
記事の内容を参考にしながら自分は以下のような状態になりました。
サンプルデータを準備します。
RegistSampleData.swift
import CoreData
func registSampleData(context: NSManagedObjectContext) {
let userSeeds: [(id: UUID, name: String)] = [
(UUID(), "User A"),
(UUID(), "User B"),
(UUID(), "User C")
]
let taskSeeds: [(id: UUID, title: String, userName: String)] = [
(UUID(), "Task A", "User A"),
(UUID(), "Task B", "User B"),
(UUID(), "Task C", "User A"),
(UUID(), "Task D", "User C"),
(UUID(), "Task E", "User A"),
(UUID(), "Task F", "User B")
]
let fetchRequestUser = NSFetchRequest<NSFetchRequestResult>()
fetchRequestUser.entity = User.entity()
let users = try? context.fetch(fetchRequestUser) as? [User]
for user in users! {
context.delete(user)
}
let fetchRequestTask = NSFetchRequest<NSFetchRequestResult>()
fetchRequestTask.entity = Task.entity()
let tasks = try? context.fetch(fetchRequestTask) as? [Task]
for task in tasks! {
context.delete(task)
}
for user in userSeeds {
let newUser = User(context: context)
newUser.id = user.id
newUser.name = user.name
}
for task in taskSeeds {
let newTask = Task(context: context)
newTask.id = task.id
newTask.title = task.title
fetchRequestUser.predicate = NSPredicate(format: "name = %@", task.userName)
let users = try? context.fetch(fetchRequestUser) as? [User]
newTask.user = users![0]
}
try? context.save()
}
ユーザーの一覧を取得してテーブルを表示します。
ContentView.swift
import SwiftUI
import CoreData
struct ContentView: View {
@Environment(\.managedObjectContext) private var context
@FetchRequest(entity: User.entity(), sortDescriptors: []) private var users: FetchedResults<User>
var body: some View {
List {
ForEach(users) { user in
Section(content: {
Text(String(user.tasks!.count))
}, header: {
Text(user.name!)
})
}
}
.onAppear {
registSampleData(context: context)
}
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView().environment(\.managedObjectContext, PersistenceController.preview.container.viewContext)
}
}
現状画像のような表示になると思います。
ユーザーの名前と属するタスクの数を表示しています。

2. ユーザーに属するタスクを取得する
ユーザーに属するタスクを取得するためには user.tasks
という記述が必要なのですが、
戻り値がNSSet?
となっています。
これを以下のように変換して[Task]
を取得できるようにします。
NSSet? -> Set<Task>? -> [Task]
コードは以下です。
let taskSet = user.tasks! as? Set<Task> // NSSet? -> Set<Task>?
let tasks = taskSet!.map { task in
return task
} // Set<Task>? -> [Task]
3. タスクの一覧を画面に表示する
上記で紹介したコードをContentView.swiftに組み込みます。
ContentView.swift
import SwiftUI
import CoreData
struct ContentView: View {
@Environment(\.managedObjectContext) private var context
@FetchRequest(entity: User.entity(), sortDescriptors: []) private var users: FetchedResults<User>
var body: some View {
List {
ForEach(users) { user in
Section(content: {
let taskSet = user.tasks! as? Set<Task>
let tasks = taskSet!.map { task in
return task
}
ForEach(tasks) { task in
Text(task.title!)
}
}, header: {
Text(user.name!)
})
}
}
.onAppear {
registSampleData(context: context)
}
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView().environment(\.managedObjectContext, PersistenceController.preview.container.viewContext)
}
}
結果、画像のようにユーザーに属するタスクの一覧が表示されます。

参考リンク