UPGRADE YOUR SKILLS: Learn advanced Swift and SwiftUI on Hacking with Swift+! >>

Expandable list with disparate objects

Forums > SwiftUI

I am creating an app with a contacts like view. I'm using Core Data, and I have a "company" entity, and a "contact" entitiy. There is a one-to-many relationship, where a company can have many contacts, but a contact can only have one company.

I'd like to create a list of companies, with the ability to "expand" the list to show all the contacts in that company in-line.

I first looked at using the built-in children property of list, but that requires the objects be of the same type.

Now I'm trying to manually create this using a disclosure group.

When I include the disclosure group as part of the list, it seems to work with individual views:

import SwiftUI

struct CompaniesView: View {
    @Environment(\.managedObjectContext) var moc
    @FetchRequest(sortDescriptors: []) var companies: FetchedResults<Company>

    var body: some View {
        NavigationView {
            List {
                ForEach(companies, id: \.self) { company in
                    CompanyRow(company: company)
                }
            }
        }
    }
}

struct CompanyRow: View {
    @ObservedObject var company: Company
    @Environment(\.managedObjectContext) var moc

    var body: some View {
        VStack(alignment: .leading) {
            Text("\(company.wrappedName)")
                .font(.headline)
            DisclosureGroup("Show contacts") {
                Text("Person A")
                Text("Person B")
                Text("Person C")
            }
        }
    }
}

Screen Shot 1

However, I'd like each item to show up as it's own row in the list, so I've tried putting in another list around the contact elements, but the view doesn't grow to show each item.

import SwiftUI

struct CompaniesView: View {
    @Environment(\.managedObjectContext) var moc
    @FetchRequest(sortDescriptors: []) var companies: FetchedResults<Company>

    var body: some View {
        NavigationView {
            List {
                ForEach(companies, id: \.self) { company in
                    CompanyRow(company: company)
                }
            }
        }
    }
}

struct CompanyRow: View {
    @ObservedObject var company: Company
    @Environment(\.managedObjectContext) var moc

    var body: some View {
        VStack(alignment: .leading) {
            Text("\(company.wrappedName)")
                .font(.headline)
            DisclosureGroup("Show contacts") {
                List {
                    Text("Person A")
                    Text("Person B")
                    Text("Person C")
                }
            }
        }
    }
}

Screen Shot 2

I'm not sure if there is a way to make this work or if I should be looking for an entirely new solution, but any advice is apprecaited!

2      

Have you considered using a @SectionedFetchRequest? It allows you to create a section identifier (In this case the company) for the contacts fetch request.

Then you would iterate through the results with a sectioned list.

Apple has an example of both here taken from their quake demo app: https://developer.apple.com/documentation/swiftui/sectionedfetchresults

That gives you every item as it's own list row...but may not help with the collapsable issue. If you give the sectioned list a style of .listStyle(SidebarListStyle()), it is collapsable...but is "open" by default.

I'm not sure how to trigger SwiftUI to load the view with the sectioned collapsed.

2      

TAKE YOUR SKILLS TO THE NEXT LEVEL If you like Hacking with Swift, you'll love Hacking with Swift+ – it's my premium service where you can learn advanced Swift and SwiftUI, functional programming, algorithms, and more. Plus it comes with stacks of benefits, including monthly live streams, downloadable projects, a 20% discount on all books, and free gifts!

Find out more

Sponsor Hacking with Swift and reach the world's largest Swift community!

Reply to this topic…

You need to create an account or log in to reply.

All interactions here are governed by our code of conduct.

 
Unknown user

You are not logged in

Log in or create account
 

Link copied to your pasteboard.