0

Following the apple tutorial "Scrumdinger" app (https://developer.apple.com/tutorials/app-dev-training/creating-a-navigation-hierarchy) I've learned a great deal about displaying data within a list. However, I've run into a small problem. My project's navigation hierarchy/data models take a slightly more complex turn from the Scrumdinger app.

Here is the desired end state for "RateDetailView" which is a child view of "PayRateView." There should be one of these for the several aircraft fleet types:

DesiredEndState

The trouble I'm having is constructing my CardView to properly pull data from the Fleet Model. Once I get the CardView ironed out, everything else should populate appropriately.

Here is my latest attempt at a CardView (with errors):

error2

struct RateCardView: View {
var fleet: Fleet

var body: some View {
    ForEach(fleet.rates) { rate in
        HStack {
            Text("Year \(rate.year)")
            Spacer()
            Text("\(rate.foHourlyRate)")
            Spacer()
            Text("\(rate.captHourlyRate)")
        }
    }
}
}

Here is my Model data... it has an Array within an Array, which is where this diverges from the apple Scrumdinger tutorial:

struct Fleet: Identifiable {
let id: UUID
var fleetName: String
var rates: [HourlyRates]

init(id: UUID = UUID(), fleetName: String, rates: [HourlyRates]) {
    self.id = id
    self.fleetName = fleetName
    self.rates = rates
}
}
extension Fleet {
static let fleetList: [Fleet] = [
 Fleet(fleetName: "B717", rates: [HourlyRates(year: [1,2,3,4,5,6,7,8,9,10,11,12], foHourlyRate: [91,126,148,152,155,159,163,167,169,171,173,174], captHourlyRate: [0,235,236,238,240,242,244,246,248,250,252,254,256])]),
 Fleet(fleetName: "B737-7/8", rates: [HourlyRates(year: [1,2,3,4,5,6,7,8,9,10,11,12], foHourlyRate: [91,126,148,152,155,159,163,167,169,171,173,174], captHourlyRate: [0,235,236,238,240,242,244,246,248,250,252,254,256])]),
 Fleet(fleetName: "B737-9", rates: [HourlyRates(year: [1,2,3,4,5,6,7,8,9,10,11,12], foHourlyRate: [91,126,148,152,155,159,163,167,169,171,173,174], captHourlyRate: [0,235,236,238,240,242,244,246,248,250,252,254,256])]),
 Fleet(fleetName: "B757", rates: [HourlyRates(year: [1,2,3,4,5,6,7,8,9,10,11,12], foHourlyRate: [91,126,148,152,155,159,163,167,169,171,173,174], captHourlyRate: [0,235,236,238,240,242,244,246,248,250,252,254,256])]),
 Fleet(fleetName: "B767-4", rates: [HourlyRates(year: [1,2,3,4,5,6,7,8,9,10,11,12], foHourlyRate: [91,126,148,152,155,159,163,167,169,171,173,174], captHourlyRate: [0,235,236,238,240,242,244,246,248,250,252,254,256])]),
 Fleet(fleetName: "A220", rates: [HourlyRates(year: [1,2,3,4,5,6,7,8,9,10,11,12], foHourlyRate: [91,126,148,152,155,159,163,167,169,171,173,174], captHourlyRate: [0,235,236,238,240,242,244,246,248,250,252,254,256])]),
 Fleet(fleetName: "A319/320", rates: [HourlyRates(year: [1,2,3,4,5,6,7,8,9,10,11,12], foHourlyRate: [91,126,148,152,155,159,163,167,169,171,173,174], captHourlyRate: [0,235,236,238,240,242,244,246,248,250,252,254,256])]),
 Fleet(fleetName: "A321", rates: [HourlyRates(year: [1,2,3,4,5,6,7,8,9,10,11,12], foHourlyRate: [91,126,148,152,155,159,163,167,169,171,173,174], captHourlyRate: [0,235,236,238,240,242,244,246,248,250,252,254,256])]),
 Fleet(fleetName: "A330", rates: [HourlyRates(year: [1,2,3,4,5,6,7,8,9,10,11,12], foHourlyRate: [91,126,148,152,155,159,163,167,169,171,173,174], captHourlyRate: [0,235,236,238,240,242,244,246,248,250,252,254,256])]),
 Fleet(fleetName: "A350", rates: [HourlyRates(year: [1,2,3,4,5,6,7,8,9,10,11,12], foHourlyRate: [91,126,148,152,155,159,163,167,169,171,173,174], captHourlyRate: [0,235,236,238,240,242,244,246,248,250,252,254,256])])
]
}
struct HourlyRates: Identifiable {
let id: UUID
var year: [Int]
var foHourlyRate: [Double]
var captHourlyRate: [Double]

init(id: UUID = UUID(), year: [Int], foHourlyRate: [Double], captHourlyRate: [Double]) {
    self.id = id
    self.year = year
    self.foHourlyRate = foHourlyRate
    self.captHourlyRate = captHourlyRate
}
}

My parent "PayRateView" should navigate to multiple child "RateDetailView"s for each fleet type:

struct PayRateView: View {
var fleet: [Fleet]

var body: some View {
    NavigationView {
        List {
            ForEach(fleet, id: \.fleetName) { plane in
                NavigationLink(destination: RateDetailView(fleet: fleet)) {
                    Text(plane.fleetName)
                }
            }
        }
        .navigationTitle("Delta Fleet Pay Rates")
    }
}
}

Here is my PayRateDetailView:

struct RateDetailView: View {
var fleet: [Fleet]

var body: some View {
    List {
        ForEach (fleet, id: \.fleetName) { line in
            RateCardView(fleet: fleet)
        }
    }
}
}

UPDATE:

error2

1 Answer 1

1

The way that you are trying to access the hourly rates in your Fleet model is the problem. You can access properties using dot-notation.

To retrieve the list of hourly rates (so the [HourlyRates]) for a fleet, use fleet.rates. This will be an array of rates, and for each rate, you want to display an HStack displaying the year, foHourlyRate, and captHourlyRate.

Also take into account the difference between fleet = [Fleet] and fleet = Fleet. The former is an array of fleets, meaning fleet.rates would be a compile error (an array does not have a property called rates). The latter is a single Fleet object, which has, as you have defined, a property rates that can be accessed. This property contains an array of HourlyRates (i.e. [HourlyRates]) which can then be looped over using ForEach.

struct RateCardView: View {
    var fleet: Fleet // You are displaying a single fleet's rates, so don't use [Fleet]

    var body: some View {
        // ForEach will loop over an array (in this case the array of `HourlyRate`s) and produce a view for each element.
        ForEach(fleet.rates) { rate in
            HStack {
                Text("Year \(rate.year)"
                Spacer()
                Text("\(rate.foHourlyRate)")
                Spacer()
                Text("\(rate.captHourlyRate)")
            }
        }
    }
}

Regarding the HourlyRates object

As it stands, you're creating each Fleet with a single HourlyRates object that contains arrays of Ints and Doubles, whereas you want (I assume) an array of HourlyRates with each a single Int, Double, etc. for their property. See below.

static let fleetList: [Fleet] = [
    Fleet(fleetName: "B717", rates: [HourlyRates(year: [1,2,3,4,5,6,7,8,9,10,11,12], foHourlyRate: [91,126,148,152,155,159,163,167,169,171,173,174], captHourlyRate: [0,235,236,238,240,242,244,246,248,250,252,254,256])])

    // Should be:
    Fleet(fleetName: "B717", rates: [
        HourlyRate(year: 1, foHourlyRate: 91, captHourlyRate: 0),
        HourlyRate(year: 2, foHourlyRate: 126, captHourlyRate: 235),
        HourlyRate(year: 3, foHourlyRate: 148, captHourlyRate: 236),
        // ...
    ]
}
Sign up to request clarification or add additional context in comments.

5 Comments

Thank you so much! You explained the "why" behind my mistakes very well. I've updated my code but am now getting a "Instance method 'appendInterpolation(_:formatter:)' requires that '[Int]' inherit from 'NSObject'" error for each of the three Text(). I've updated the original post with the new code and a picture of the errors. Any ideas?
Similar to the Fleet vs. [Fleet] problem, the properties in your HourlyRates object are arrays ([Int], [Double]), not integers or doubles. If you change the year to var year: Int and do the same for the foHourlyRate and captHourlyRate, it should work.
I made that change to the HourlyRates object but that negatively affects the fleetList : [Fleet] constant. The year, foHourlyRate and captHourlyRate properties now are no longer suited to contain my array of data. I've included to my original post a screen grab of the associated errors.
Check my updated answer. Please also mark this question as solved (if your original question has been answered)
Thank you so much! I have marked your answers as "accepted." Could you also mark mine as having shown research effort? Also would you mind looking at my next question relative to this same project? stackoverflow.com/q/74404957/20170438 Thank you so much, you've been so very helpful!!

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.