Ser Pounce
Ser Pounce

Reputation: 14547

SwiftUI / SwiftData / CloudKit: how to make custom binding for dynamically changing setter value

In my app, I have a class called Project:

import Foundation
import SwiftData

@Model
class Project
{
    @Relationship(deleteRule: .nullify, inverse: \ProjectType.projects) var projectType: ProjectType?
    @Relationship(deleteRule: .cascade, inverse: \Category.project) var categories : [Category]?
    var lastSelectedDate: Date = Date.now
    
    init(projectType: ProjectType)
    {
        self.projectType = projectType
        self.categories = []
    }
}

Since I'm using SwiftData / CloudKit, both projectType and categories have to be optionals because they have relationships, even though both will be initialized with values and will always hold a value.

When a user selects a Project object from a list, I'd like to be able to unwrap projectType and categories before I pass them to the next view (so I don't have to constantly unwrap them throughout the app):

private func projectViewForProject(_ project:Project) -> ProjectView?
{
    if  let categories = project.categories, !categories.isEmpty,
        let initialSelectedCategory = categories.max(by: { $0.lastSelectedDate < $1.lastSelectedDate }),
        let books = initialSelectedCategory.books, !books.isEmpty
    {
        var selectedCategory = initialSelectedCategory
        
        return ProjectView(project: project,
                           categories: Binding(get: { categories }, set: { project.categories = $0 }),
                           selectedCategory: Binding(get: { selectedCategory }, set: { selectedCategory = $0 }),
                           books: Binding(get: { books }, set: { selectedCategory.books = $0 }))
    }
    else
    {
        return nil
    }
}

I'm having no issue with categories and selectedCategory, but with books I am struggling with figuring out how to pass it in since its value will be based on selectedCategory. If it's not possible to make it so the books Binding can update when selectedCategory changes, I'm fine with just passing in the inital value but I can't wrap my head around how to do this. Also, just like with categories, I need to be able to add and delete Book objects from the books array, so it's important to get the setter right. Hopefully I am being clear about this, any help for a solution would be appreciated.

Upvotes: 0

Views: 55

Answers (0)

Related Questions