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

Help on Day 47 Challenge

Forums > 100 Days of SwiftUI

Hello guys,

I can't figure it out how to pass data between content view and the detail view.

I tried several times but it won't work.

Here is my code:

struct ContentView: View {
    @StateObject var activities = Activities()
    @State private var showingAddView = false

    var body: some View {
        NavigationView {
            List {
                ForEach(activities.activities) { activity in
                    NavigationLink {
                        DetailView()
                    } label: {
                        HStack {
                            Text(activity.name)
                                .font(.headline)
                        }
                    }
                }
                .onDelete(perform: deleteRows)
            }
            .navigationTitle("Activity Tracker")
            .toolbar {
                Button {
                    showingAddView = true
                } label: {
                    Image(systemName: "plus")
                }
            }
            .sheet(isPresented: $showingAddView) {
                // more code to come
                AddActivityView()
            }
        }
    }

    func deleteRows(at offsets: IndexSet) {
        activities.activities.remove(atOffsets: offsets)
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}
import SwiftUI

struct AddActivityView: View {
    @ObservedObject var activities = Activities()
    @Environment(\.dismiss) var dismiss

    @State private var name = ""

    var body: some View {
        NavigationView {
            Form {
                TextField("Add the activity name", text: $name)
            }
            .navigationTitle("New activity")
            .toolbar {
                Button {
                    let activity = Activity(name: name, counter: 0)
                    activities.activities.append(activity)
                    dismiss()
                } label: {
                    Text("Save")
                }
                .disabled(name.isEmpty ? true : false)
            }
        }
    }
}

struct AddActivityView_Previews: PreviewProvider {
    static var previews: some View {
        AddActivityView()
    }
}
import SwiftUI

struct DetailView: View {

    var body: some View {
        NavigationView {
            Text("Hello")
        }
    }
}

struct DetailView_Previews: PreviewProvider {
    static var previews: some View {
        DetailView()
    }
}
import Foundation

struct Activity: Codable, Identifiable, Equatable {
    var id = UUID()
    var name: String
    var counter: Int
}
import Foundation

class Activities: ObservableObject {
    @Published var activities = [Activity]() {
        didSet {
            if let encoded = try? JSONEncoder().encode(activities) {
                UserDefaults.standard.set(encoded, forKey: "Activities")
            }
        }
    }

    init() {
        if let savedActivities = UserDefaults.standard.data(forKey: "Activities") {
            if let decodedActivities = try? JSONDecoder().decode([Activity].self, from: savedActivities) {
                activities = decodedActivities
                return
            }
        }
        activities = []
    }
}

Thank you all

2      

Change this in your ContentView:

AddActivityView()

to this:

AddActivityView(activities: activities)

And this in your AddActivityView:

@ObservedObject var activities = Activities()

to this:

@ObservedObject var activities: Activities

You should be passing in the Activities object to the child View but instead you are creating an entirely new one.

2      

@roosterboy Thank you so much, last question: What I have to put in the preview struct? Because it gives me an error.

2      

You need to supply an Activities object. Perhaps like so:

AddActivityView(activities: Activities())

Even better would be to have a static member on Activities that supplies example data to display in the preview.

extension Activities {
    static var previewData: Activities {
        let sample = Activities()
        sample.activities = //fill in some sample data
        return sample
    }
}

Then you could do something like:

AddActivityView(activities: Activities.previewData)

2      

Hacking with Swift is sponsored by RevenueCat

SPONSORED Take the pain out of configuring and testing your paywalls. RevenueCat's Paywalls allow you to remotely configure your entire paywall view without any code changes or app updates.

Learn more here

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.