I've created a list of food products with stored data such as calories, protein, category, etc. I've made an array of categories in order to categorize these products into groups and I'm now trying to reference this array when stating the data in each product, but when doing this (Apple variable in line 16) I get the error:
"Cannot use instance member 'categories' within property initializer; property initializers run before 'self' is available"
This is my code:
struct Product : Identifiable {
var id = UUID()
var productName : String
var calories : Double
var protein : Double
var carbs : Double
var fats : Double
var weight : Double
var category : String
}
struct Data {
#State var categories = ["Animal Products", "Dairy", "Fast Food", "Fruits", "Grains", "Nuts", "Vegetables", "Wheat"]
var Apple = Product(productName: "Apple", calories: 52, protein: 0.3, carbs: 14, fats: 0.2, weight: 80, category: categories[3])
var Avocado = Product(productName: "Avocado", calories: 160, protein: 2, carbs: 9, fats: 15, weight: 600, category: <#T##String#>)
var Banana = Product(productName: "Banana", calories: 89, protein: 1.1, carbs: 23, fats: 0.3, weight: 120, category: <#T##String#>)
var Broccoli = Product(productName: "Broccoli", calories: 34, protein: 2.8, carbs: 5, fats: 0.4, weight: 225, category: <#T##String#>)
var Burger = Product(productName: "Burger", calories: 264, protein: 13, carbs: 30, fats: 10, weight: 110, category: <#T##String#>)
var Carrot = Product(productName: "Carrot", calories: 41, protein: 0.9, carbs: 10, fats: 0.2, weight: 61, category: <#T##String#>)
var Cheerios = Product(productName: "Cheerios", calories: 379, protein: 6, carbs: 83, fats: 5, weight: 40, category: <#T##String#>)
var Cherry = Product(productName: "Cherry", calories: 50, protein: 1, carbs: 12, fats: 0.3, weight: 5, category: <#T##String#>)
}
How can I include this array inside of the Product list?
It looks like categories are predefined, then here is a solution for your case - make categories static constant:
struct Data {
static let categories = ["Animal Products", "Dairy", "Fast Food", "Fruits", "Grains", "Nuts", "Vegetables", "Wheat"]
var Apple = Product(productName: "Apple", calories: 52, protein: 0.3,
carbs: 14, fats: 0.2, weight: 80, category: categories[3])
// ... others
}
Related
I'm creating a picker in which a food product is selected from the array productList of type Product and I'm trying to create text boxes that output every variable stored in whichever product was selected. However, although the code is successfully built, the picker won't allow the user to make a selection. How can I fix this?
This is my code:
struct AddView : View {
#State var selectFood = 0
#ObservedObject var database : Database
var body: some View {
VStack{
Picker(selection: $selectFood, label: Text("What did you eat?")
.font(.title)
.fontWeight(.bold)
.foregroundColor(.white))
{
ForEach(database.productList) { (productList: Product) in
Text(productList.name)
}
}
.pickerStyle(MenuPickerStyle())
Spacer(minLength: 100)
ZStack {
Rectangle()
.frame(width: 350, height: 90, alignment: .center)
.foregroundColor(.white)
.opacity(0.25)
.offset(y: 40)
.cornerRadius(10)
Text("Calories: \(database.productList[selectFood].calories)")
}
Spacer()
Text("Enter")
Spacer()
}
.padding(.horizontal, 50)
}
}
This is the code where the array is stored:
struct Product : Identifiable {
var id = UUID()
var name : String
var calories : Double
var protein : Double
var carbs : Double
var fats : Double
var weight : Double
}
class Database : ObservableObject{
#Published var productList = [Product]()
init() {
self.productList = [
Product(name: "Apple", calories: 52, protein: 0.3, carbs: 14, fats: 0.2, weight: 80),
Product(name: "Avocado", calories: 160, protein: 2, carbs: 9, fats: 15, weight: 600),
Product(name: "Banana", calories: 89, protein: 1.1, carbs: 23, fats: 0.3, weight: 120),
Product(name: "Broccoli", calories: 34, protein: 2.8, carbs: 5, fats: 0.4, weight: 225),
Product(name: "Burger", calories: 264, protein: 13, carbs: 30, fats: 10, weight: 110),
Product(name: "Carrot", calories: 41, protein: 0.9, carbs: 10, fats: 0.2, weight: 61),
Product(name: "Cheerios", calories: 379, protein: 6, carbs: 83, fats: 5, weight: 40),
Product(name: "Cherry", calories: 50, protein: 1, carbs: 12, fats: 0.3, weight: 5),
Product(name: "Chicken Nuggets", calories: 302, protein: 16, carbs: 15, fats: 20, weight: 16),
Product(name: "Cocoa Pops", calories: 389, protein: 5, carbs: 85, fats: 2.9, weight: 45),
Product(name: "Corn Flakes", calories: 357, protein: 8, carbs: 84, fats: 0.4, weight: 45),
Product(name: "Crunchy Nuts", calories: 402, protein: 6, carbs: 82, fats: 5, weight: 45),
Product(name: "Eggs", calories: 196, protein: 14, carbs: 0.8, fats: 15, weight: 60),
Product(name: "Fries", calories: 312, protein: 3.4, carbs: 43, fats: 15, weight: 100),
Product(name: "Froasted Flakes", calories: 369, protein: 4, carbs: 89, fats: 1.7, weight: 45),
]
}
}
Type of selection should be same as type of Picker data block id or tag, so if you want selected index, then it should be like
struct AddView : View {
#State var selectFood = 0
#ObservedObject var database : Database
var body: some View {
VStack{
Picker(selection: $selectFood, label: Text("What did you eat?")
.font(.title)
.fontWeight(.bold)
.foregroundColor(.white))
{
ForEach(database.productList.indices, id: \.self) { i in // << here
Text(database.productList[i].name) // << and here
}
}
.pickerStyle(MenuPickerStyle())
// ... other code
I create Aliment struct.
And i have an array of Aliment.
struct Aliment {
let name: String
let vitamineARetinol: Float
let vitaminC: Float
let vitaminD: Float
let calories: Float
let grammage: Float
}
let ListAlimentsBrut = [
Aliment(name: "Orange", vitamineARetinol: 0.5, vitaminC: 57, vitaminD: 0.98, calories: 140, grammage: 100),
Aliment(name: "Pomme", vitamineARetinol: 0.2, vitaminC: 6.25, vitaminD: 0.38, calories: 120, grammage: 100),
Aliment(name: "Poire", vitamineARetinol: 0.1, vitaminC: 4.62, vitaminD: 0.58, calories: 140, grammage: 100),
Aliment(name: "Laitue", vitamineARetinol: 0.3, vitaminC: 4.72, vitaminD: 0.92, calories: 105, grammage: 100),
Aliment(name: "Laitue", vitamineARetinol: 0.7, vitaminC: 4.72, vitaminD: 0.63, calories: 122, grammage: 100),
Aliment(name: "Poivron Jaune", vitamineARetinol: 0, vitaminC: 184, vitaminD: 0, calories: 29.2, grammage: 100)
]
how can i access the calorie value of the second food, i mean 120 calories for "Pomme", but through programming and not directly.
Thank you.
You can access the second element of the an array using the subscript method (arrayProperty[index]), note that the first element has an index of 0, in your case :
ListAlimentsBrut[1].calories
Also, I would recommend to follow the naming convention in swift meaning that the property ListAlimentsBrut should start with a lower case and to name the property without saying the type of the data (here list)and keeping consistency between language (just english, not a mix of french and english) like that for exemple :
let rawIngredients = [...]
I have 2 arrays of objects. I would like to add a category property to each object in values, example: 50 should fall in the range 41 to 70
let values = [
{1: 124},
{2: 50},
{3: 65},
{4: 21}
];
let categories = [
{cat: "Category1", min: 5, max: 40},
{cat: "Category2", min: 41, max: 70},
{cat: "Category3", min: 71, max: 130}
];
How do I get my result as, using array method forEach():
[
{1: 124, category: "Category3"},
{2: 50, category: "Category2"},
{3: 65, category: "Category2"},
{4: 21, category: "Category1"}
]
Not an optimized one but satisfies the requirement.
let result = [];
values.forEach(element => {
categories.forEach(col => {
let current = Object.values(element)[0];
if(current >= col.min && current <=col.max){
element["category"] = col.cat;
}
})
result.push(element);
})
I can set up the list fine and even have a select or deselect button in the detail view (CardView). The problem I encounter is when I click select I want to add it to an array (cardSelected). If "name3" is the 1st in the list how can I find out the index to add to the cardSelected array?
I'm new to programming so looking for some guidance. Thanks
import Foundation
import SwiftUI
class Cards: ObservableObject {
#Published var cardSelected = [gameCards]()
#Published var playerCards = [gameCards]()
#Published var playerGameCards = [
gameCards(id: 1, name: "name1", attack: 92, defence: 49, gameControl: 60, creativity: 72, legend: 4),
gameCards(id: 2, name: "name2", attack: 87, defence: 40, gameControl: 65, creativity: 80, legend: 2),
gameCards(id: 3, name: "name3", attack: 43, defence: 93, gameControl: 40, creativity: 45, legend: 3),
gameCards(id: 4, name: "name4", attack: 88, defence: 51, gameControl: 80, creativity: 92, legend: 5),
gameCards(id: 5, name: "name5", attack: 85, defence: 51, gameControl: 72, creativity: 81, legend: 3),
gameCards(id: 6, name: "name6", attack: 91, defence: 38, gameControl: 72, creativity: 89, legend: 5),
gameCards(id: 7, name: "name7", attack: 34, defence: 95, gameControl: 40, creativity: 50, legend: 5),
gameCards(id: 8, name: "name8", attack: 86, defence: 63, gameControl: 89, creativity: 84, legend: 4),
gameCards(id: 9, name: "name9", attack: 90, defence: 30, gameControl: 50, creativity: 83, legend: 5),
gameCards(id: 10, name: "name10", attack: 32, defence: 92, gameControl: 42, creativity: 32, legend: 4)
]
}
struct gameCards: Identifiable {
let id: Int
let name: String
let attack: Int
let defence: Int
let gameControl: Int
let creativity: Int
let legend: Int
import SwiftUI
struct CardView: View{
var carddetail: String
#EnvironmentObject var cardselected: Cards
#State var cardSelect: Bool = false
var body: some View{
ZStack{
VStack{
Text(carddetail)
Spacer()
if cardSelect == false {
Button(action:{
self.cardSelect = true
below ?? is where I want to add the index but don't know how to programmatically find it.
self.cardselected.cardSelected.append(self.cardselected.playerCards[??])
print("\([self.carddetail])")
print("\([self.cardselected.cardSelected.description])")
}){
if cardSelect == false {
Image(systemName: "star")
}
if cardSelect == true{
Image(systemName: "star.fill")
}
}
}
if cardSelect == true {
Button(action:{
self.cardSelect = false
}){
if cardSelect == false {
Image(systemName: "star")
}
if cardSelect == true{
Image(systemName: "star.fill")
}
}
}
Spacer()
}
}
}
}
struct ContentView: View {
#EnvironmentObject var playerList: Cards
var body: some View {
NavigationView{
ZStack{
Image("Background").resizable().edgesIgnoringSafeArea(.all)
VStack{
Image("FLTitle").resizable().frame(width: 400, height: 100)
Spacer()
Text("Collected Cards")
Text("Choose 5")
ScrollView(.horizontal){
HStack{
Image("Back")
Image("Back")
Image("Back")
Image("Back")
Image("Back")
}.padding(.horizontal)
}
Spacer()
HStack{
NavigationView{
List(playerList.playerCards) {gc in
NavigationLink(destination: CardView(carddetail: gc.name)){
Text("\(gc.name)")
}
}.navigationBarTitle("Card detail").font(.body)
}.padding(.leading).frame(width: UIScreen.main.bounds.size.width/2, height: 200)
Text("Opposition").padding(.trailing).frame(width: UIScreen.main.bounds.size.width/2, height: 200).background(Color.red)
}
Spacer()
}
}
}.navigationBarTitle("", displayMode: .inline).navigationBarBackButtonHidden(true).navigationBarHidden(true)
}
}
let data = Cards()
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView().environmentObject(data)
}
}
When creating the List you can use ForEach to access the index and then pass to CardView
List {
ForEach(0..<playerList.playerCards.count) { index in
NavigationLink(destination: CardView(carddetail: self.playerList.playerCards[index].name,
index: index)) {
Text("\(self.playerList.playerCards[index].name)")
}
}.navigationBarTitle("Card detail").font(.body)
}
I'm very new to programming and I'm having trouble with the more complex aspects. I am trying to use a data set called playerCameCards and randomly add 5 of these to playerCards. I have managed to do that but I want to display name: of the last added element but I can't figure out how to do it. I'd be grateful for some help Below is my code.
import Foundation
import SwiftUI
class Cards: ObservableObject {
#Published var playerCards = [gameCards]()
#Published var playerGameCards = [
gameCards(id: 1, name: "name1", attack: 92, defence: 49, gameControl: 60, creativity: 72, legend: 4),
gameCards(id: 2, name: "name2", attack: 87, defence: 40, gameControl: 65, creativity: 80, legend: 2),
gameCards(id: 3, name: "name3", attack: 43, defence: 93, gameControl: 40, creativity: 45, legend: 3),
gameCards(id: 4, name: "name4", attack: 88, defence: 51, gameControl: 80, creativity: 92, legend: 5),
gameCards(id: 5, name: "name5", attack: 85, defence: 51, gameControl: 72, creativity: 81, legend: 3),
gameCards(id: 6, name: "name6", attack: 91, defence: 38, gameControl: 72, creativity: 89, legend: 5),
gameCards(id: 7, name: "name7", attack: 34, defence: 95, gameControl: 40, creativity: 50, legend: 5),
gameCards(id: 8, name: "name8", attack: 86, defence: 63, gameControl: 89, creativity: 84, legend: 4),
gameCards(id: 9, name: "name9", attack: 90, defence: 30, gameControl: 50, creativity: 83, legend: 5),
gameCards(id: 10, name: "name10", attack: 32, defence: 92, gameControl: 42, creativity: 32, legend: 4)
]
}
struct gameCards: Identifiable {
let id: Int
let name: String
let attack: Int
let defence: Int
let gameControl: Int
let creativity: Int
let legend: Int
}
import SwiftUI
struct ContentView: View {
#EnvironmentObject var cardData: Cards
#State var firstTime: Bool = false
#State var currentCard: String = "Back"
var body: some View {
ZStack{
VStack{
Spacer()
Text("Lets open your 1st cards").background(Color.white).font(.title)
Spacer()
Below is where I want show the name e.g. "name1" from the last element added to my playerCards array. I may want to make this an image in the future and use the ID: to display the corresponding image but I'm unable to access the types in my array
Text("I want to show the "name" of the element in the last array I've just used").frame(width: 200, height: 200).background(Color.blue)
Spacer()
Button(action:{
if self.cardData.playerCards.count <= 4{
self.cardData.playerCards.append(self.cardData.playerGameCards.randomElement()!)
print("\([self.cardData.playerCards.last])")
}
if self.cardData.playerCards.count > 4 {
self.firstTime = true
}
}){
if self.cardData.playerCards.count <= 4 {
Image("Click").renderingMode(.original).resizable().frame(width: 100, height: 100)
}
else{
NavigationLink(destination: ContentView()){Image("Continue").renderingMode(.original).resizable().frame(width: 100, height: 100)
}
}
}
}
}
}
}
This is how to embed a value in a String in Swift:
if self.cardData.playerCards.last != nil {
Text("I want to show the \(self.cardData.playerCards.last!.name) of the element in the last array I've just used")
}