NEW: Learn to build amazing SwiftUI apps for macOS with my new book! >>

SOLVED: Day 41: Moonshot App confused by code

Forums > 100 Days of SwiftUI

In the Merging Codable structs video Paul

adds this code to the MissionView view:

struct CrewMember {
        let role: String
        let astronaut: Astronaut
    }

    let crew: [CrewMember]

and this custom initializer:

 init(mission: Mission, astronauts: [String: Astronaut]) {
      self.mission = mission
      self.crew = mission.crew.map { member in
          if let astronaut = astronauts[member.name] {
              return CrewMember(role: member.role, astronaut: astronaut)
          } else {
              fatalError("Missing \(member.name)")
          }
      }
  }

I'm confused why we need to do all that when adding this to MissionView:

let astronaut: [String: Astronaut]

and passing astronauts from ContentView

  NavigationLink {
      MissionView(mission: mission, astronaut: astronauts)
  }

gives us access to the same information in MissionView:

ForEach(mission.crew, id: \.self) { crewMember in
      VStack {
          Text(crewMember.name)
          Text(crewMember.role)
          Image(astronaut[crewMember.name, default: Astronaut(id: "Error", name: "Error", description: "Error")].id)
      }
 }

my full version of MissionView:

struct MissionView: View {
    let mission: Mission
    let astronaut: [String: Astronaut]

    var body: some View {
        GeometryReader { geometry in
            ScrollView {
                VStack {
                    Image(mission.image)
                        .resizable()
                        .scaledToFit()
                        .frame(maxWidth: geometry.size.width * 0.6)
                        .padding(.top)
                    VStack(alignment: .leading) {
                        Text("Mission Highlights")
                            .font(.title.bold())
                            .padding(.bottom, 5)
                        Text(mission.description)
                    }
                    .padding(.horizontal)

                }
                .padding(.bottom)
                ScrollView(.horizontal) {
                    HStack {
                        ForEach(mission.crew, id: \.self) { crewMember in
                            VStack {
                            Text(crewMember.name)
                            Text(crewMember.role)
                            Image(astronaut[crewMember.name, default: Astronaut(id: "Error", name: "Error", description: "Error")].id)
                            }
                        }
                    }
                }
            }
            .navigationTitle(mission.displayName)
            .navigationBarTitleDisplayMode(.inline)
            .background(.darkBackground)
        }
    }
}

1      

It uses .map which is a powerful feature of the language.

.map, together with .filter and more recently introduced .compactMap are things worth getting familar and comfortable with.

1      

That doesn't really answer my question. (Ok. I guess according to roosterboy below, it does answer my question. Thanks.) I realize he uses .map. My point is why bother with all that when the data can be directly accessed as shown in my example. What is being gained by doing it the way he did it?

1      

when the data can be directly accessed as shown in my example

Your code:

Text(crewMember.name) //shows armstrong

would have to be changed to this:

Text(astronauts[crewMember.name]!.name) //shows Neil A. Armstrong

to get an equivalent of what Paul has. Because CrewMember.name does not contain the same data as Astronaut.name.

Apart from that, @Greenamberred is pretty much correct that the code was meant to serve as an example of using functions like map.

1      

This was just a place holder text view: Text(crewMember.name) //shows armstrong

Like the image, I would have had this for the actual name:

Text(astronaut[crewMember.name, default: Astronaut(id: "Error", name: "Error", description: "Error")].name)

Or I could have forced it with the exclamation point like you're demonstrating. That actually didn't occur to me, so that's a good point as well.

I plan on using Paul's code, I just couldn't understand why he was doing it that way and it sounds like you're both saying it was just to demonstrate .map functionality. So, I'll just leave it at that. Thanks for the responses.

1      

Hacking with Swift is sponsored by RevenueCat

SPONSORED Spend less time managing in-app purchase infrastructure so you can focus on building your app. RevenueCat gives everything you need to easily implement, manage, and analyze in-app purchases and subscriptions without managing servers or writing backend code.

Get Started

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.