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

Day 73 - BucketList Challenges - Best practice question and reminder about modifiers on Group

Forums > 100 Days of SwiftUI

NOTE This is a question about best practices when coding.

After completing the challenge tasks, I noticed that my ContentView had a ZStack which in turn displays my CompleteMapView with another ZStack. See below:

ContentView:

struct ContentView: View {
    @State private var isUnlocked = false

    var body: some View {
        Group {
            if isUnlocked {
                CompleteMapView()
            } else {
                UnlockButton(isUnlocked: $isUnlocked)
            }
        }
    }
}

CompleteMapView:

    var body: some View {
        ZStack {
            MapView(centerCoordinate: $centerCoordinate, selectedPlace: $selectedPlace, showingPlaceDetails: $showingPlaceDetails, annotations: locations)
                .edgesIgnoringSafeArea(.all)
                .alert(isPresented: $showingPlaceDetails) {
                    Alert(title: Text(selectedPlace?.title ?? "Unknown"), message: Text(selectedPlace?.subtitle ?? "Missing place information."), primaryButton: .default(Text("OK")), secondaryButton: .default(Text("Edit")) {
                            self.showingEditScreen = true
                    })
                }
            Circle()
                .fill(Color.blue.opacity(0.3))
                //.opacity(0.3)
                .frame(width: 32, height: 32)

            VStack {
                Spacer()
                HStack {
                    Spacer()
                    Button(action: {
                        let newLocation = CodableMKPointAnnotation()
                        newLocation.coordinate = self.centerCoordinate
                        newLocation.title = "Example location"
                        self.locations.append(newLocation)

                        self.selectedPlace = newLocation
                        self.showingEditScreen = true
                    }) {
                        Image(systemName: "plus")
                            .padding()
                            .background((Color.black.opacity(0.75)))
                            .foregroundColor(.white)
                            .font(.title)
                            .clipShape(Circle())
                            .padding(.trailing)
                    }
                }
            }
        }
        .sheet(isPresented: $showingEditScreen, onDismiss: saveData) {
            if self.selectedPlace != nil {
                EditView(placemark: self.selectedPlace!)
            }
        }
        .onAppear(perform: loadData)
    }

I thought I'd be smart and change the CompleteMapView from a ZStack to a Group.

The app appears to launch and run just fine... but I noticed that in the terminal, I get the following print...

Data successfully loaded from DocumentsDirectory.

Data successfully loaded from DocumentsDirectory.

Data successfully loaded from DocumentsDirectory.

.onAppear(peform: loadData) is now being run 3 times, apparently being run for each of the 3 Views inside my Group (MapView, Circle, and VStack). I tested adding another View inside Group and sure enough, it adds a 4th call to loadData.

Switching it back to a ZStack makes it work. Also, just moving the .onAppear inside the group and attaching it to the MapView seems to work.

I'm not sure what the best coding practice is. Those elements are designed to be shown over each other in a particular order, so grouping them with Group could lead to trouble down the road if CompleteMapView gets called in anything other than a ZStack, right?

This all started because I found it redundant showing a ZStack (CompleteMapView) inside a ZStack (ContentView).

Any thoughts on best practice would be appreciated.

3      

Hi! I realize this was awhile ago, but thought I'd post in case it helps anyone. I took a similar approach to you, except I have no Group. My Wiki fetch doesn't work but I think it's an unrelated issue, because everything else about the app is working well, including saving the data. This is my entire ContentView:

struct ContentView: View {
  @State private var isUnlocked = false

  var body: some View {
    if isUnlocked {
      FullMapView()
    } else {
      PlacesButtonView(isUnlocked: $isUnlocked)
    }
  }
}

3      

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!

Archived topic

This topic has been closed due to inactivity, so you can't reply. Please create a new topic if you need to.

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.