CoreData issue SwiftUI - core-data

I am new in Swift and am working on a project using core data. I created my entity (called StudentData) comprehensive of all the attributes that I am using in my coding. I have a view with a list of clients and when you tap on each of them a view with some attributes will show, here is the code:
struct StudentView: View {
#Environment (\.presentationMode) var presentationMode
#Environment(\.managedObjectContext) var managedObjectContext
#State private var showingSheet = false
#State var selectedStudent = StudentData()
let myStudent: StudentData
var body: some View {
HStack {
Text("Subject")
.font(.system(size: 30, weight: .bold, design: .rounded))
.foregroundColor(.red)
.padding(.horizontal)
Spacer()
Text("\(myStudent.subject ?? "No Subject")")
.font(.title2)
.bold()
.foregroundColor(.white)
.padding(.horizontal)
}
HStack {
Text("School Year")
.font(.system(size: 30, weight:.bold, design: .rounded))
.foregroundColor(.red)
.padding(.horizontal)
Spacer()
Text("Year \(myStudent.schoolYear ?? "Unknown")")
.font(.title2)
.bold()
.foregroundColor(.white)
.padding(.horizontal)
}
HStack {
Text("Address")
.font(.system(size: 30, weight: .bold, design: .rounded))
.foregroundColor(.red)
.italic()
.padding(.horizontal)
Spacer()
Spacer()
Button(action: {
showingSheet = true
}) {
Text(("\(myStudent.address ?? "Unknown")")).underline()
}
}.navigationBarTitle(myStudent.name ?? "No Name")
.navigationBarItems(trailing:
NavigationLink(destination: DetailView(myStudent:selectedStudent)) {
Text("More Details")
Moving to the DetailView the code is:
#Environment(\.managedObjectContext) var managedObjectContext
#FetchRequest(entity: StudentData.entity(), sortDescriptors: [],
animation: .spring()) var chapter: FetchedResults<StudentData>
#Environment (\.presentationMode) var presentationMode
#State var showModalView = false
let myStudent: StudentData
#State var selectedStudent = StudentData()
var body: some View {
VStack{
Text("Topics Covered")
.font(.system(size: 30, weight: .bold, design: .rounded))
.foregroundColor(.red)
.padding(.horizontal)
Text("\(myStudent.chapter ?? "-")")
.font(.title2)
.bold()
.foregroundColor(.white)
.padding(.horizontal)
}
}.sheet(isPresented: $showModalView, content: {
TopicView(topic: selectedStudent)})
However when I tap on the button to show the detail view the app crashes and this error shows:
*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[StudentData chapter]: unrecognized selector sent to instance 0x60000157b380'
terminating with uncaught exception of type NSException.
So I understand the error is clearly related to the attribute 'chapter' in my entity but I don't really figure out what I am doing wrong.
Thanks for anyone who'll help.

Related

Swiftui-Picker doesn't show selected value [duplicate]

This question already has an answer here:
Choosing CoreData Entities from form picker
(1 answer)
Closed 9 months ago.
Initial position: making two pickers filled from database where the second depends on the first. I followed this Picker Values from a previous picker - CoreData/SwiftUI example and it works pretty good.
Only one problem: the second picker doesn't show the selected value.
#State var courtSelected = 0
#State var judgeSelected = 0
HStack{
Picker(selection: $courtSelected, label: Text("Gericht \(courtSelected)")){
ForEach(0..<courts.count){ court in
Text("\(courts[court].name ?? "Unknown")")
}
}
}
HStack {
Picker(selection: $judgeSelected, label: Text("Richter: (\(judgeSelected))")){
ForEach(Array(courts[courtSelected].courtsJudges! as! Set<Judges>), id: \.self) { judge in
Text("\(judge.gender ?? "") \(judge.title ?? "") \(judge.name ?? "")")
}
}
}
Only differences:
the modification from NSSet to array
I had to change #Binding var judgeSelected:Int to #State, because otherwise I have to hand over the judge selected as Parameter beginning from App-Struct.
Printing the $judgeSelected inside the label demonstrates, that this var is never changed.
Your selection and presentation are differ by type, so add tag:
Picker(selection: $courtSelected, label: Text("Gericht \(courtSelected)")){
ForEach(0..<courts.count){ court in
Text("\(courts[court].name ?? "Unknown")").tag(court) // << here !!
}
}
Second picker presents objects, so selection should also be an object, like
#State var judgeSelected: Judges? = nil
Next shows similar case so should be helpful https://stackoverflow.com/a/68815871/12299030
try something like this:
HStack{
Picker(selection: $courtSelected, label: Text("Gericht \(courtSelected)")){
ForEach(0..<courts.count){ court in
Text("\(courts[court].name ?? "Unknown")")
}
}
}
HStack {
Picker(selection: $judgeSelected, label: Text("Richter: (\(judgeSelected))")){
// -- here
ForEach(Array(Set(courts[courtSelected].courtsJudges!)), id: \.self) { judge in
Text("\(judge.gender ?? "") \(judge.title ?? "") \(judge.name ?? "")")
}
}.id(UUID()) // <-- here
}
}
Note also the second ForEach with Set. PS, do not use forced unwrap, ie. no ! in your code.
EDIT-1: to avoid the error with arrayLiteral, try this:
HStack {
Picker(selection: $judgeSelected, label: Text("Richter: (\(judgeSelected))")){
if let theJudges = courts[courtSelected].courtsJudges {
ForEach(Array(Set(theJudges)), id: \.self) { judge in
Text("\(judge.gender ?? "") \(judge.title ?? "") \(judge.name ?? "")")
}
}
}.id(UUID())
}
EDIT-2:
here is my test code that allows the second picker
to depend on the first picker. I used both the id marker, and tag that
must match the selection type.
Since you don't show your struct code for court and judge,
I created some example structs for those.
You will have to adjust the code to cater for your structs.
Used the id of the Judge struct in the second picker for the tag.
However, there are other ways to have a Int tag, for example using array indices, such as:
struct Judge: Identifiable, Hashable {
var id: Int
var gender: String?
var name: String?
var title: String?
}
struct Court: Identifiable, Hashable {
var id: Int
var name: String?
var courtsJudges: [Judge]?
}
struct ContentView: View {
#State var courtSelected = 0
#State var judgeSelected = 0
#State var courts: [Court] = [
Court(id: 0, name: "one",
courtsJudges: [
Judge(id: 0, gender: "Male", name: "name1", title: "title1"),
Judge(id: 1, gender: "Male", name: "name2", title: "title2"),
Judge(id: 2, gender: "Male", name: "name3", title: "title3")
]),
Court(id: 1, name: "two",
courtsJudges: [
Judge(id: 3, gender: "Female", name: "name7", title: "title7"),
Judge(id: 4, gender: "Female", name: "name8", title: "title8"),
Judge(id: 5, gender: "Female", name: "name9", title: "title9")
])
]
var body: some View {
VStack (spacing: 77) {
HStack{
Picker(selection: $courtSelected, label: Text("Gericht \(courtSelected)")){
ForEach(0..<courts.count) { court in
Text("\(courts[court].name ?? "Unknown")").tag(court)
}
}
}
HStack {
Picker(selection: $judgeSelected, label: Text("Richter: (\(judgeSelected))")){
if let theJudges = courts[courtSelected].courtsJudges {
ForEach(Array(Set(theJudges))) { judge in
Text("\(judge.gender ?? "") \(judge.title ?? "") \(judge.name ?? "")")
.tag(judge.id)
}
}
}.id(UUID())
}
}.padding()
}
}
Alternatively:
HStack {
Picker(selection: $judgeSelected, label: Text("Richter: (\(judgeSelected))")){
if let theJudges = courts[courtSelected].courtsJudges, let arr = Array(Set(theJudges)) {
ForEach(arr.indices, id: \.self) { index in
Text("\(arr[index].gender ?? "") \(arr[index].title ?? "") \(arr[index].name ?? "")")
.tag(index)
}
}
}.id(UUID())
}
First: thanks for all the great help so far.
Bringing it all together til now.
The following code creates a picker, but the selection is not shown. Changing to a radioGroup, you can't select anything.
Here's my edited code
struct ContentView: View {
#Environment(\.managedObjectContext) private var viewContext
#FetchRequest(
sortDescriptors: [NSSortDescriptor(keyPath: \Courts.name, ascending: true)],
animation: .default
)
private var courts: FetchedResults<Courts>
#State var courtSelected = 0
#State var judgeSelected = 0
var body: some View {
HStack{
Picker(selection: $courtSelected, label: Text("Gericht")){
ForEach(0..<courts.count){ court in
Text("\(courts[court].name ?? "Unknown")").tag(court)
}
}
}
HStack {
Picker(selection: $judgeSelected, label: Text("Richter \(judgeSelected)")){
ForEach(Array(courts[courtSelected].courtsJudges as! Set<Judges>), id: \.self) { judge in
Text("\(judge.gender ?? "") \(judge.title ?? "") \(judge.name ?? "")").tag(judge)
}
}.id(UUID())
}
}
}
The next code still leads to an error
HStack {
Picker(selection: $judgeSelected, label: Text("Richter: (\(judgeSelected))")){
if let theJudges = courts[courtSelected].courtsJudges {
ForEach(Array(Set(theJudges)), id: \.self) { judge in
Text("\(judge.gender ?? "") \(judge.title ?? "") \(judge.name ?? "")")
}
}
}.id(UUID())
}
I think, the problem has to be anywhere else, because already at the start the picker doesn't show anything and the radios are grey.
Is it, because picker 2 depends on picker 1 and changes when a value in picker 1 is selected?
It's all for macOS on xcode 13.4.1
I created a complete new project with core data, added two entities (Courts and Judges) with two attributes each (id and name).
Then I only made this view:
import SwiftUI
import CoreData
struct ContentView: View {
#Environment(\.managedObjectContext) private var viewContext
#FetchRequest(
sortDescriptors: [NSSortDescriptor(keyPath: \Courts.name, ascending: true)],
animation: .default
)
private var courts: FetchedResults<Courts>
#FetchRequest(
sortDescriptors: [NSSortDescriptor(keyPath: \Judges.name, ascending: true)],
animation: .default
)
private var judges: FetchedResults<Judges>
#State var courtSelected = 0
#State var judgeSelected = 0
var body: some View {
if(courts.count > 0) {
HStack{
Picker(selection: $courtSelected, label: Text("Gericht")){
ForEach(0..<courts.count){ court in
Text("\(courts[court].name ?? "Unknown")").tag(court)
}
}
}
HStack {
Picker(selection: $judgeSelected, label: Text("Richter \(judgeSelected)")){
ForEach(Array(courts[courtSelected].courtsJudges as! Set<Judges>), id: \.self) { judge in
Text("\(judge.name ?? "")").tag(judge)
}
}.id(UUID())
}
HStack {
Button("neue Gerichte") {
addItem()
addJudges()
}
}
}
}
private func addItem() {
for id in 0..<3 {
let newItem = Courts(context: viewContext)
newItem.id = UUID()
newItem.name = "Gericht Nr. \(id)"
do {
try viewContext.save()
} catch {
// Replace this implementation with code to handle the error appropriately.
// fatalError() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development.
let nsError = error as NSError
fatalError("Unresolved error \(nsError), \(nsError.userInfo)")
}
}
}
private func addJudges() {
for cd in 0..<courts.count {
for jd in 0..<3 {
let newJudge = Judges(context: viewContext)
newJudge.id = UUID()
newJudge.name = "Richter \(jd) am Gericht \(courts[cd].name)"
newJudge.judgesCourts = courts[cd]
try? viewContext.save()
}
}
}
}
The result: both pickers are shown, first ist ok, second shows the right judges, but they are not "selectable"

SwiftUI CoreData - How to update the fetch request and the list

I am creating an application in SwiftUI using CoreData and I have a problem. In application you can add song to favorites and it will be added to list (FavoriteSongsView). Until the song is added to favorites everything is fine. In DetailView I click the button and the "heart.fill" icon and the song is added to the list. However, if I click on the icon again to un-favorite the song, it does not disappear from the list. I fought with it a little bit but without any effect. Could you please point out the cause of the problem?
List of favorite songs:
#Environment(\.managedObjectContext) var managedObjectContext
#FetchRequest(
entity: Song.entity(),
sortDescriptors: [NSSortDescriptor(keyPath: \Song.number, ascending: true)],
predicate: NSPredicate(format: "favorite <> 'false'")
) var songs: FetchedResults<Song>
var body: some View {
NavigationView{
VStack{
List {
ForEach(songs, id:\.self){ song in
NavigationLink(destination: DetailView(song: song, isSelected: song.favorite)) {
HStack{
Text("\(song.number). ") .font(.headline) + Text(song.title ?? "No title")
}
}
}
}
}
.listStyle(InsetListStyle())
.navigationTitle("Favorite")
}
}
}
Detailed view:
struct DetailView: View {
#State var song : Song
#State var isSelected: Bool
#State var wrongNumber: Bool = false
var body: some View {
VStack{
Text(song.content!)
.padding()
Spacer()
}
.navigationBarTitle("\(song.number). \(song.title ?? "No title")", displayMode: .inline)
.toolbar {
ToolbarItemGroup(placement: .navigationBarTrailing) {
HStack{
Button(action: {
song.favorite.toggle()
PersistenceController.shared.save()
isSelected=song.favorite
}) {
Image(systemName: "heart.fill")
.foregroundColor(isSelected ? .red : .blue)
}
Button(action: {
alert()
}) {
Image(systemName: "1.magnifyingglass")
}
NavigationLink("DetailView", destination: DetailView(song: song, isSelected: isSelected))
.frame(width: 0, height: 0)
.hidden()
}
}
}
}
}
Use this NSPredicate
NSPredicate(format: "favorite = %d", false)

Core Data, Problem with updating (duplicating instead)

I am new to Swift UI. Could you please help me with core data updating?
Here is the point of a problem:
I am building a WatchOS app. There are 3 Views there:
FirstView - a view with a button to Add a new Goal and a List of added Goals.
AddGoalView - appears after pressing Add new Goal.
RingView - a view with a Goal Ring (similar to activity ring mechanics) and all the data presented.
The point of the problem is the next:
After adding a new Goal everything is alright. The Data passes correctly from AddGoalView to the FirstView. I need only 2 items to be passed out of AddGoalView (One String and one Double).
Then, after pressing on the recently created Goal I appear on the Ring View. I successfully pass there 2 items (that String and Double I mentioned).
On the RingView I want to update the 3-rd Item (double) and send it back. So it can be updated on the FirstView.
the Result:
Instead of updating this 3-d Item it just seems to create a completely new Goal on the First View below the previous Goal. Photo
My Code (FirstView):
struct FirstView: View {
#FetchRequest (
entity:NewGoal.entity(),
sortDescriptors:[NSSortDescriptor(keyPath: \NewGoal.dateAdded, ascending: false)],
animation: .easeInOut )
var results:FetchedResults<NewGoal>
#State var showMe = false
var body: some View {
ScrollView{
VStack{
VStack(alignment: .leading){
Text("My Goals:")
NavigationLink(
destination: AddGoalView(),
isActive: $showMe,
label: {
Image(systemName: "plus")
Text("Set Money Goal")
})
Text("Recents:")
ForEach(results){ item in
VStack(alignment: .leading){
NavigationLink(
destination: RingView(GTitle: item.goalTitle ?? "", Sum: item.neededSum),
label: {
HStack{
Image(systemName: "gear")
VStack(alignment: .leading){
Text(item.goalTitle ?? "")
HStack{
Text("$\(item.yourSum, specifier: "%.f")") ///This item doesn't update
Text("/ $\(item.neededSum, specifier: "%.f")")
}
}
}
})
}
}
}
}
}
}
}
My Code (AddGoalView):
struct AddGoalView: View {
#State private var goalTitle = ""
#State private var showMe:Bool = true
#State private var neededSum:Double = 0.0
#State private var isFocusedNum = false
#Environment(\.managedObjectContext) var context
#Environment(\.presentationMode) var presentationMode
var body: some View {
ScrollView{
VStack (alignment: .leading, spacing: 6){
TextField("Goal Name...", text: $goalTitle)
HStack{
Text("$\(neededSum, specifier: "%.f")")
.overlay(
RoundedRectangle(cornerRadius: 9)
.stroke(isFocusedNum ? Color.red : Color.white, lineWidth: 1)
.opacity(1.0))
.focusable(true) { newState in isFocusedNum = newState}
.animation(.easeInOut(duration: 0.1), value: isFocusedNum)
.digitalCrownRotation(
$neededSum,
from: 0,
through: 100000,
by: 25,
sensitivity: .high)
}
Button(action: addGoal) {
Text("Add Goal")
}
.disabled(neededSum == 0.0)
.disabled(goalTitle == "")
.navigationTitle("Edit")
}
}
}
private func addGoal(){
let goal = NewGoal(context: context)
goal.goalTitle = goalTitle
goal.dateAdded = Date()
goal.neededSum = neededSum
do{
try context.save()
presentationMode.wrappedValue.dismiss()
}catch let err{
print(err.localizedDescription)
}
}
My Code (RingView Code):
struct RingView: View {
#State private var isFocusedSum = false
#State private var yournewSum:Double = 0.0
var goalItem: NewGoal?
var Sum:Double
var GTitle:String
#Environment(\.managedObjectContext) var context
#Environment(\.presentationMode) var presentationMode
#FetchRequest var results: FetchedResults<NewGoal>
init(GTitle: String, Sum: Double){
self.GTitle = GTitle
self.Sum = Sum
let predicate = NSPredicate(format:"goalTitle == %#", GTitle)
self._results=FetchRequest(
entity: NewGoal.entity(),
sortDescriptors: [NSSortDescriptor(keyPath: \NewGoal.dateAdded, ascending: false)],
predicate: predicate,
animation: .easeInOut
)
}
var body: some View {
ZStack{
ForEach(results) { item in
RingShape(percent:(yournewSum/item.neededSum*100), startAngle: -90, drawnClockwise: false) /// Ring
.stroke(style: StrokeStyle(lineWidth: 10, lineCap: .round))
.fill(AngularGradient(gradient: Gradient(colors: [.red, .pink, .red]), center: .center))
.frame(width: 155, height: 155)
HStack(alignment: .top){
Spacer()
Button(action: addSum) { ///BUTTON TO Update
Image(systemName: "gear")
}
.clipShape(Circle())
}
VStack(alignment: .trailing, spacing: 0.0){
Spacer()
Text("$\(yournewSum, specifier: "%.f")") /// Here is the data I want to change via Digital Crown and update
.font(.title3)
.overlay(
RoundedRectangle(cornerRadius: 7)
.stroke(Color.white, lineWidth: 2)
.opacity(isFocusedSum ? 1.0:0.0)
)
.focusable(true) { newState in isFocusedSum = newState}
.animation(.easeInOut(duration: 0.3), value: isFocusedSum)
.digitalCrownRotation(
$yournewSum,
from: 0,
through: Double((item.neededSum)),
by: 10,
sensitivity: .high)
Text("/ $\(item.neededSum, specifier: "%.f")") ///Here is the Double data I entered in AddGoalView
.font(.caption)
}
.frame(width: 200, height: 230)
.padding(.top, 7)
VStack(alignment: .center, spacing: 1.0){
Text(item.goalTitle ?? "Your Goal Name") ///Here is the String data I entered in AddGoalView
.foregroundColor(.gray)
}
.padding(.top, 200.0)
}
}
.padding([.top, .leading, .trailing], 5.0)
}
private func addSum(){
let goal = goalItem == nil ? NewGoal(context: context): goalItem
goal?.yourSum = yournewSum //// I am trying to update the Data here, but after running the func it creates a duplicate.
do{
try context.save()
presentationMode.wrappedValue.dismiss()
} catch let err{
print(err.localizedDescription)
}
}
You never give var goalItem: NewGoal? the initial value of the item you want to update.
try replacing this
RingView(GTitle: item.goalTitle ?? "", Sum: item.neededSum)
with
RingView(goalItem: item, GTitle: item.goalTitle ?? "", Sum: item.neededSum)
and of course your have to change your initializer for RingView to
init(goalItem: NewGoal? = nil, GTitle: String, Sum: Double){
and add to the initializer this line
self.goalItem = goalItem

Updating core data entity with observedobject

I have created a list of clients which get saved in core data. I added some attributes through an AddView and now I am trying to add a new attribute using a different view. In order to do that I understood I need to use the observedObject property wrapper so that it doesn't create a new client but update the existing one. This is the code:
import SwiftUI
import CoreData
struct TopicView: View {
#Environment(\.managedObjectContext) var managedObjectContext
#Environment (\.presentationMode) var presentationMode
#ObservedObject var topic: StudentData
#State var content = ""
#State private var show = false
#StateObject private var keyboard = Keyboard()
var body: some View {
Form{
Section (header: Text("Topics covered")
.bold()
.padding(.all)
.font(.title3)) {
TextEditor(text: Binding(
get: {self.topic.content ?? ""},
set: {self.topic.content = $0 } ))
.frame(height: 250)
}
}.onTapGesture {
hideKeyboard()
}
}
}
Button ("Submit")
{
self.topic.content = self.content
self.topic.objectWillChange.send()
try? self.managedObjectContext.save()
self.presentationMode.wrappedValue.dismiss()
}.foregroundColor(.white)
This is the view where the new attribute should be shown:
import SwiftUI
import CoreData
import MapKit
struct StudentView: View {
#Environment(\.managedObjectContext) var managedObjectContext
#FetchRequest(entity: StudentData.entity(),
sortDescriptors: [],
animation: .spring()) var content: FetchedResults<StudentData>
#Environment (\.presentationMode) var presentationMode
#ObservedObject var topic: StudentData
#State var showModalView = false
#State private var showingSheet = false
let myStudent: StudentData
var body: some View {
NavigationView {
VStack{
Text("Topics Covered")
.font(.system(size: 30, weight: .bold, design: .rounded))
.foregroundColor(.red)
.padding(.horizontal)
Text("\(myStudent.content ?? "")")
.font(.title2)
.bold()
.foregroundColor(.white)
.padding(.horizontal) }}
Spacer()
Spacer()
}.sheet(isPresented: $showModalView, content: {
TopicView(topic: topic)})
The problem is, if I type in the texteditor some text without save it then it shows correctly in the other view. However, when I save it, it does not show in the other view.
Is there anything wrong in my save code?

SwiftUI - Unable to reference #Published value outside Struct

I am new to SwiftUI and am hoping for some assistance with a project I am developing.
I am unable to reference #published value outside a struct.
All values are correctly functioning within the struct using:
#ObservableObject
#Publihsed
#ObservedObject
I have a Struct within ContentView which is linked to another View where I would like to display Quantity and Costs.
I have attempted various ways to access the values as can be seen in the struct NewOrders, but I keep getting zero and not getting the updated value.
Am I missing a step or executing code incorrectly?
Thanks in advance
class MealOrders: ObservableObject {
//Jollof Rice - Published
#Published var jollof = 0
//Swallow - Published
#Published var swallow = 0
//Pepper Soup - Published
#Published var pepperSoup = 0
}
struct ContentView: View {
var body: some View {
VStack {
NavigationView {
Section {
VStack(alignment: .leading) {
NavigationLink(destination: MenuOption()) {
Text("Meal Options")
}
Spacer()
.frame(minWidth: 0, maxWidth: .infinity, minHeight: 0, maxHeight:
.infinity, alignment: .topLeading)
}.padding() //Vstack End
}
Section {
VStack {
Image("africanfoods")
.resizable()
.frame(width: 275.0, height: 250.0)
.clipShape(Circle())
.overlay(Circle().stroke(Color.black, lineWidth: 5))
.scaledToFit()
}
} //Section End
Section { //Social Media
VStack {
Spacer()
HStack {
Spacer()
Image("facebook")
.resizable()
.frame(width:40, height: 40)
.scaledToFit()
.padding()
Image("instergram")
.resizable()
.frame(width:40, height: 40)
.scaledToFit()
.padding()
Image("youtube")
.resizable()
.frame(width:40, height: 40)
.scaledToFit()
.padding()
Image("twitter")
.resizable()
.frame(width:40, height: 40)
.scaledToFit()
.padding(.horizontal, 50)
}
} //Vstack End
} //Social Media
.navigationBarTitle(Text("African Foods Center"))
} //NavView End
} //VStack End
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
struct MenuOption: View {
//Object Observed Declarations
#ObservedObject var meals = MealOrders()
//Meal Prices
#State private var jolloRiceUnitCost = 14.95 //Jollof Rice Unit Cost
#State private var swallowUnitCost = 12.50 //Swallow Unit Cost
#State private var pepperSoupUnitCost = 13.50 //Pepper Soup Unit Cost
#State private var deliveryCost = 5.99 //Delivery Cost
#State private var menuItem = 0
var menuItems = ["Rice Meals", "Swallow Meals", "Pepper Soups"]
//Meals Calculator
var calculateMeal: Double {
var orderCost = 0.0
//Jollof Rice
if menuItems[menuItem] == "Rice Meals" {
orderCost = self.jolloRiceUnitCost * Double(self.meals.jollof)
return orderCost
//Swallow - Pounded Yam / Eba
} else if menuItems[menuItem] == "Swallow Meals" {
orderCost = self.swallowUnitCost * Double(self.meals.swallow)
} else if menuItems[menuItem] == "Pepper Soups" {
orderCost = self.pepperSoupUnitCost * Double(self.meals.pepperSoup)
}
return orderCost
}
var body: some View {
VStack(alignment: .leading) {
Section(header: Text("Select Meal").padding(.horizontal, 25)) {
Picker("Select Item", selection: $menuItem) {
ForEach(0 ..< menuItems.count) {
Text(self.menuItems[$0])
}
}.pickerStyle(SegmentedPickerStyle())
.padding(.horizontal, 25)
if menuItems[menuItem] == "Rice Meals" {
Text("Rice Meals:")
.foregroundColor(.black)
.padding(.horizontal, 25)
Spacer().frame(height:20)
`Text("Rice meals consist of Jollof Rice, Rice and Stew, Fried
Rice. You can option in meat, fish and or plantain with any of the meals")`
.foregroundColor(.blue)
.lineLimit(nil)
.padding(.horizontal, 25)
Spacer().frame(height:60)
//Insert image - Jollof Rice
Image("jollofRice")
.resizable()
.frame(width:250, height: 250)
.scaledToFit()
.border(Color.black, width: 4)
.padding(.horizontal, 100)
Spacer().frame(height:20)
HStack {
Stepper("Quantity (Max 5)",value: $meals.jollof, in: 0...5)
.padding(.horizontal, 45)
Text("\(meals.jollof): £\(calculateMeal, specifier: "%.2f")")
.padding()
}.padding()
Section { //Button Order
VStack {//Add Stepper for Quantity
Spacer()
HStack(alignment: .center, spacing: 140) {
Spacer()
Button(action: {}) {
NavigationLink(destination: Text("Jollof:: \(meals.jollof), £\(calculateMeal, specifier: "%.2f")")) {
Text("Create Order")
.font(.system(size: 14))
.padding()
.background(Color.blue)
.foregroundColor(.white)
.cornerRadius(6)
}.padding()
Spacer()
}
}
} //Vstack End
} //Button Section End
} else if menuItems[menuItem] == "Swallow Meals" {
Text("Swallow")
.foregroundColor(.green)
.padding(.horizontal, 25)
Spacer().frame(height:20)
`Text("Swallow is the colloqual word for Pounded Yam, Eba, Fufu or Amala. This is complemented with soups, such as Egusi, Okra etc. You could have this meal with either meat or fish")`
.foregroundColor(.blue)
.lineLimit(nil)
.padding(.horizontal, 25)
Spacer().frame(height:60)
//Inset Image
Image("poundedYamEgusi")
.resizable()
.frame(width:250, height:250)
.scaledToFit()
.border(Color.black, width: 4)
.padding(.horizontal, 100)
HStack {//Add Stepper for Quantity
Stepper("Quantity (Max 5)",value: $meals.swallow, in: 0...5)
.padding(.horizontal, 45)
Text("\(meals.swallow): £\(calculateMeal, specifier: "%.2f")")
.padding()
}.padding()
//Insert Order Button
Section {
VStack {
Spacer()
HStack(alignment: .center, spacing: 140) {
Spacer()
Button(action: {}) {
NavigationLink(destination: Text("Swallow: \(meals.swallow), £\(calculateMeal, specifier: "%.2f")")) {
Text("Create Order")
.font(.system(size: 14))
.padding()
.background(Color.blue)
.foregroundColor(.white)
.cornerRadius(6)
}.padding()
Spacer()
}
}
} //VStack End
} //Section End
} else if menuItems[menuItem] == "Pepper Soups" {
Text("Pepper Soup")
.foregroundColor(.red)
.padding(.horizontal, 25)
Spacer().frame(height:20)
`Text("Pepper soup is normally taken after one has had either Pounded Yam or rice meals. Depending on the audeience, the soup can be lightly spicy to very hot. Pepper soup can be had with either fish or meat")`
.foregroundColor(.blue)
.lineLimit(nil)
.padding(.horizontal, 25)
Spacer().frame(height:60)
//Insert Image
Image("pepperSoupYam")
.resizable()
.frame(width:250, height:250)
.scaledToFit()
.border(Color.black, width: 4)
.padding(.horizontal, 100)
HStack {//Add Stepper Quantity for Pepper Soup
Stepper("Quantity (5 Max)",value: $meals.pepperSoup, in: 0...5)
.padding(.horizontal, 45)
Text("\(meals.pepperSoup): £\(calculateMeal, specifier: "%.2f")")
.padding()
}.padding()
//Inset Order Button
Section {
VStack {
Spacer()
HStack(alignment: .center, spacing: 140) {
Spacer()
Button(action: {}) {
NavigationLink(destination: NewOrders()) {
Text("Create Order")
.font(.system(size: 14))
.padding()
.background(Color.blue)
.foregroundColor(.white)
.cornerRadius(6)
}.padding()
Spacer()
}
}
}
}
}
Spacer()
}.font(.system(size: 14))
.foregroundColor(.purple)
} //Vstack Ending
} //View Ending
}
//This sis going to be the Orders Struct
struct NewOrders: View {
#ObservedObject var orderUpdatedV2 = MealOrders()
#State private var orderUpdate = MenuOption().meals.jollof
var body: some View {
//let mealsU: ContentView
NavigationView{
VStack {
List {
Text("")
}
}
}.navigationBarTitle("Meal Order")
}
}
This line below is incorrect because creates new value, that's why you have nil
#State private var orderUpdate = MenuOption().meals.jollof
instead you need to have (as far as I understood your code)
#Binding var orderUpdate: Int
and pass it in place of creating
NavigationLink(destination: NewOrders(orderUpdate: $meals.jollof)) {
Note: This is the idea, I'm not sure copy/paste will work, because provided your code snapshot is not compilable at my side.

Resources