Taeeun Kim
Taeeun Kim

Reputation: 1256

How can I use relationship in ForEach in CoreData using SwiftUI?

The problem has been solved by 'hackingwithswift' website

Just follow the steps on the link! "https://www.hackingwithswift.com/books/ios-swiftui/one-to-many-relationships-with-core-data-swiftui-and-fetchrequest"

original ask

I would like to use elements of [relationship]
But whatever I try, it doesn't work..
There is something, what I missed and, sadly I don't know what that would be until now :/

First of all, I want to show my core data model and code.

Core Data Model Image

Entity: Page, Attribute: name(String), relationship: toCard
Entity: Card, Attribute: title(String), price(Double), relationship: toPage

Scenario: Page has multiple cards
One to Many (One page to many cards)

ContentView.swift 

TabView(selection: self.$pageIndex){
MainPageView()

ForEach(pages, id: \.self) { page in
    SubPageView(whichPage: page)
    }
}
SubPageView.swift

@Environment(\.managedObjectContext) var moc
@FetchRequest(entity: Page.entity(),
              sortDescriptors: [NSSortDescriptor(keyPath: \Page.name, ascending: true),
                                NSSortDescriptor(keyPath: \Page.toCard, ascending: true)]
) var pages: FetchedResults<Page>
@FetchRequest(entity: Card.entity(),
              sortDescriptors: [NSSortDescriptor(keyPath: \Card.title, ascending: true),
                                NSSortDescriptor(keyPath: \Card.price, ascending: true)]
) var cards: FetchedResults<Card>

var whichPage: FetchedResults<Page>.Element

ForEach(pages, id: \.self) { page in // page: 1번 2번 3번

    if whichPage == page {
    
        ForEach(Array(whichPage.toCard! as Set), id: \.self) { relationshipFromToCard in

        }
}

The Problem is here

ForEach(Array(whichPage.toCard! as Set), id: \.self) { item in
    CardView(price: item.price, title: item.title ?? "Unknown")
}

I can not use like this in CardView.
Xcode doesn't show the Attributes of Card, because they are not matching.
How can I fix it..?

The data of Card has been saved in relationship (code below)

let card = Card(context: self.moc)
card.title = self.title
card.price = self.doubleValue
selectedPage?.addToToCard(card)

Upvotes: 1

Views: 1612

Answers (1)

Taeeun Kim
Taeeun Kim

Reputation: 1256

I solved this problem with help from this awesome 'hackingwithswift' website! Just follow the steps on the link!

https://www.hackingwithswift.com/books/ios-swiftui/one-to-many-relationships-with-core-data-swiftui-and-fetchrequest

Edited:

  1. Goto .xcdatamodeld file

  2. Click Entity -> Class -> Codezen to Manual/None

  3. Editor -> Create NSManagedObject Subclass

  4. Add in Page+CoreDataProperties.swift

    public var wrappedName: String {
         name ?? "Unknown Title"
     }
    
     public var cardArray: [Card] {
         let set = toCard as? Set<Card> ?? []
    
         return set.sorted {
             $0.wrappedTitle < $1.wrappedTitle
         }
     }
    
  5. Add in "Card+CoreDataProperties.swift"

    public var wrappedTitle: String {
         title ?? "Unknown Title"
     }
    
     public var wrappedPrice: Double {
         price
     }
    
  6. Now you can use relationship's value like this!

ForEach(pages, id: \.self) { page in
    if whichPage == page {
        ForEach(page.cardArray, id: \.self) { card in
            VStack {
                CardView(price: card.wrappedPrice, title: card.wrappedTitle)
            }
        }
    }
}

Upvotes: 4

Related Questions