1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

ユーザーに属するタスクを取得して画面に一覧表示する

Posted at

概要

CoreDataを使って以下のような関係を作りました。
User : Task = 1 : n
あるユーザーに属するタスクの一覧を取得するときは user.tasks みたいな感じで取得できると思ってたのですが、取得できませんでした。
今回の記事でユーザーに属するタスクを取得して画面に表示する方法を紹介します。

環境

macOS Monterey 12.1
Xcode 13.2.1

手順

  1. CoreDataを使ってUser : Task = 1 : nを表現する(記事の主題から外れるため詳しい説明は割愛)
  2. ユーザーに属するタスクの一覧を取得する
  3. 取得したタスクの一覧を画面に表示する

1. User : Task = 1 : nを表現する

↑こちらの記事を参考にしました。
コードは以下です。
記事の内容を参考にしながら自分は以下のような状態になりました。

User Entity
スクリーンショット 2022-01-01 0.57.58.png

Task Entity
スクリーンショット 2022-01-01 0.58.01.png

サンプルデータを準備します。

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)
    }
}

結果、画像のようにユーザーに属するタスクの一覧が表示されます。

参考リンク

1
1
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
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?