Post

Replies

Boosts

Views

Activity

Reply to Issues with implementing the logical code for my timesheetKeyin
to be able to Bind & @state this with the following logic & the swift file I want to link it with This is not clear. Please explain what you want to have instead of the print here ? if isSet { // == true { print("true is \(isSet)") } else { print("false is\(isSet)") } If I understand your code, Binding works the other way. I could not test, so there may be other changes needed elsewhere. Change as follows: struct TimeKeyInRow: View,Identifiable { var id: String var project: Project @State var isSet: Bool // This is the State, not the Binding let listOfPossibleHours: [Double] = [0.5,1,2,3,4,8] var body: some View { HStack { Text(project.shortname.paddedToWidth(10)) // Text(projects[1].shortname) .font(.custom("Menlo", size: 16)) .frame(width: 120.0) Spacer() ForEach(listOfPossibleHours, id: \.self) { hour in HourButton(id: "\(project.shortname)", isSet: $isSet, value: hour) // $isSet as it is to a Binding } Text("\(project.leftPMtime)") } } } and struct HourButton: View,Identifiable { var id: String = "hour" @Binding var isSet: Bool // Here is the Binding, not State Note: when you post a screenshot, reduce its size, no need to have such a large image.
Topic: UI Frameworks SubTopic: SwiftUI Tags:
Feb ’24
Reply to Creating an Array/Button with specific ID everybutiton regardless of projectName or Hours
I actually also spot that if I put your code into a LIST then the code is not working anymore strange behaviour What do you mean ? What code do you pour where ? What do you get (error, crash, wrong result ?) I have tested this, it works: var body: some View { List { //VStack(spacing: 10) { ForEach(Array(filteredProjects.enumerated()), id: \.offset) { (row, project) in TimeKeyInRow(id: project.shortname, project: project, isSet: $isSet[row]) } } If id is an Int in JSON, you can have an Int in Project for id as well: struct Project: Identifiable { var id: Int = 0// UUID = UUID() var name: String var shortname: String var leftPMtime: Int var isTeco: Bool // other stuff Just declare it when you load projects (either in code or you retrieve from JSON) .onAppear() { // <<-- Added projects = [ Project(id: 1, name: "Project1, isTeco = false, shortname = MORN, leftPMTime = 131",shortname : "MORN", leftPMtime : 131, isTeco: false), Project(id: 2, name: "Project2, isTeco = false, shortname = MORN, leftPMTime = 122",shortname : "IFF", leftPMtime : 122, isTeco: true), Project(id: 3, name: "Project3, isTeco = false, shortname = MORN, leftPMTime = 133",shortname : "FFI", leftPMtime : 133, isTeco: true), Project(id: 4, name: "Project4, isTeco = false, shortname = MORN, leftPMTime = 444",shortname : "IFFCO", leftPMtime : 444, isTeco: false) ] for (row, project) in filteredProjects.enumerated() { isSet[row] = !project.isTeco } } Why do you declare as private: private var coordinates: Coordinates You'd better do this: struct Project: Hashable, Codable,Identifiable { var id: Int var name: String var shortname: String var leftPMtime: Int var state: String var description: String var isFeatured: Bool var isSpecific: Bool var isFavorite: Bool var isTeco: Bool var coordinates: Coordinates Finally, you said I try to use UUID as per your recommendation and the mentioned of the. link below but code keys is way to much in term of string as to be decodable I need to use all the variables inside the project..... which is way to much and some of them are GPS coordinates. here is a glimpse of one project in my JSON Could you explain what the problem is, I don't understand your concern.
Topic: UI Frameworks SubTopic: SwiftUI Tags:
Feb ’24
Reply to Creating an Array/Button with specific ID everybutiton regardless of projectName or Hours
You should open a new thread, as it is another question. And show how you generate and parse the JSON. But, first, why do you need id here ? struct TimeKeyinList: View, Identifiable { var id: String = "" This works: struct TimeKeyinList: View { // , Identifiable { // var id: String = "" // to ease test @State var projects = [Project] () You should probably remove the id from the JSON, keep id as UUID and define codingKeys, except for id: struct Project: Identifiable { var id: UUID = UUID() var name: String var shortname: String var leftPMtime: Int var isTeco: Bool private enum CodingKeys : String, CodingKey { case name, shortname, leftPMtime, isTeco } } See details here: https://stackoverflow.com/questions/64348019/using-uuid-with-json-in-swift
Topic: UI Frameworks SubTopic: SwiftUI Tags:
Feb ’24
Reply to Creating an Array/Button with specific ID everybutiton regardless of projectName or Hours
It works with the code I sent previously: But you did not use what I proposed. Problem is here: why declare projects inside a single project ? That does not make sense, that must be global what is this init() in Project: it sets the same short name for all ? in TimeKeyinList, projects is not initialized struct TimeKeyinList: View, Identifiable { var id: String = "" // to ease test var projects = [Project] () @State var isSet: [Bool] = [true, false, false, true] @State private var hideTeco = false var filteredProjects: [Project] { // removeTECO project projects.filter { project in !project.isTeco }} var body: some View { VStack { ForEach(Array(filteredProjects.enumerated()), id: \.offset) { (row, project) in TimeKeyInRow(id: project.shortname, project: project, isSet: $isSet[row]) } } .labelsHidden() .onAppear() { // <<-- Added for (row, project) in filteredProjects.enumerated() { isSet[row] = !project.isTeco } } } } struct Project: Identifiable { var id: UUID = UUID() var name: String var shortname: String var leftPMtime: Int var isTeco: Bool var projects = [ (id: UUID.init(), name: "Project1, isTeco = false, shortname = MORN, leftPMTime = 111",shortname : "MORN", leftPMtime : 111, isTeco: false), (id: UUID.init(), name: "Project2, isTeco = true, shortname = IFF, leftPMTime = 222",shortname : "IFF", leftPMtime : 222, isTeco: true), (id: UUID.init(), name: "Project3, isTeco = true, shortname = FFI, leftPMTime = 333",shortname : "FFI", leftPMtime : 333, isTeco: true), (id: UUID.init(), name: "Project4, isTeco = false, shortname = IFFCO, leftPMTime = 444",shortname : "IFFCO", leftPMtime : 444, isTeco: false) ] init(id: UUID, name: String, shortname: String, leftPMtime: Int, isTeco: Bool) { self.id = id self.name = "project1" self.shortname = "MORN" self.leftPMtime = 131 self.isTeco = true } } So, the correct code is as follows (I modified slightly to show you how you could initialise projects: struct TimeKeyInRow: View,Identifiable { var id: String var project: Project /* Do not redeclare, that would hide the global projects var var projects = [ Project(name: "Project1, isTeco = false, shortname = MORN, leftPMTime = 131",shortname : "MORN", leftPMtime : 131, isTeco: false), Project(name: "Project2, isTeco = false, shortname = MORN, leftPMTime = 122",shortname : "IFF", leftPMtime : 122, isTeco: true), Project(name: "Project3, isTeco = false, shortname = MORN, leftPMTime = 133",shortname : "FFI", leftPMtime : 133, isTeco: true), Project(name: "Project4, isTeco = false, shortname = MORN, leftPMTime = 444",shortname : "IFFCO", leftPMtime : 444, isTeco: false) ] */ @Binding var isSet: Bool let listOfPossibleHours: [Double] = [0.5, 1, 2, 3, 4, 8] var body: some View { HStack { Spacer() // ADDED Text(project.shortname.paddedToWidth(5)) // Text(projects[1].shortname) .font(.custom("Menlo", size: 16)) // <<-- To get proper alignment Spacer() ForEach(listOfPossibleHours, id: \.self) { hour in HourButton(id: "\(project.shortname)", isSet: isSet, value: hour) } Text("\(project.leftPMtime)") .font(.custom("Menlo", size: 16)) // <<-- To get proper alignment Spacer() // ADDED } } } struct TimeKeyinList: View, Identifiable { var id: String = "" // to ease test @State var projects = [Project] () // Now need a State var to be able to modify later @State var isSet: [Bool] = [true, false, false, true] @State private var hideTeco = false var filteredProjects: [Project] { // removeTECO project projects.filter { project in !project.isTeco }} var body: some View { VStack(spacing: 10) { ForEach(Array(filteredProjects.enumerated()), id: \.offset) { (row, project) in TimeKeyInRow(id: project.shortname, project: project, isSet: $isSet[row]) } } .labelsHidden() .onAppear() { // <<-- Added ; projects initialized here projects = [ Project(name: "Project1, isTeco = false, shortname = MORN, leftPMTime = 131",shortname : "MORN", leftPMtime : 131, isTeco: false), Project(name: "Project2, isTeco = false, shortname = MORN, leftPMTime = 122",shortname : "IFF", leftPMtime : 122, isTeco: true), Project(name: "Project3, isTeco = false, shortname = MORN, leftPMTime = 133",shortname : "FFI", leftPMtime : 133, isTeco: true), Project(name: "Project4, isTeco = false, shortname = MORN, leftPMTime = 444",shortname : "IFFCO", leftPMtime : 444, isTeco: false) ] for (row, project) in filteredProjects.enumerated() { isSet[row] = !project.isTeco } } } } Note : if you want more space between rows, change : var body: some View { VStack(spacing: 10) { // <<-- more spacing ForEach(Array(filteredProjects.enumerated()), id: \.offset) { (row, project) in TimeKeyInRow(id: project.shortname, project: project, isSet: $isSet[row]) } }
Topic: UI Frameworks SubTopic: SwiftUI Tags:
Feb ’24
Reply to Creating an Array/Button with specific ID everybutiton regardless of projectName or Hours
You do not show how you initialise @State var isSet: [Bool] Why do you repeat projects initialisation in TimeKeyInRow and in TimeKeyinList ? If I understand your intent, you should only pass a single project. So, I have added an initialisation in .onAppear. This is just a quick test. Of course, you have to update isBool each time a isTeco toggles or each time you add a new Project. That's just a quick fix, to show the principle. extension String { // To align text func paddedToWidth(_ width: Int) -> String { let length = self.count guard length < width else { return self } let spaces = Array<Character>.init(repeating: " ", count: width - length) return self + spaces } } struct TimeKeyInRow: View,Identifiable { var id: String var project: Project. // Just pass the project /* Do not redeclare var projects = [ Project(name: "Project1, isTeco = false, shortname = MORN, leftPMTime = 131",shortname : "MORN", leftPMtime : 131, isTeco: false), Project(name: "Project2, isTeco = false, shortname = MORN, leftPMTime = 122",shortname : "IFF", leftPMtime : 122, isTeco: true), Project(name: "Project3, isTeco = false, shortname = MORN, leftPMTime = 133",shortname : "FFI", leftPMtime : 133, isTeco: true), Project(name: "Project4, isTeco = false, shortname = MORN, leftPMTime = 444",shortname : "IFFCO", leftPMtime : 444, isTeco: false) ] */ @Binding var isSet: Bool let listOfPossibleHours: [Double] = [0.5,1,2,3,4,8] var body: some View { HStack { Spacer() // ADDED Text(project.shortname.paddedToWidth(5)) // Text(projects[1].shortname) .font(.custom("Menlo", size: 16)) // <<-- To get proper alignment Spacer() ForEach(listOfPossibleHours, id: \.self) { hour in HourButton(id: "\(project.shortname)", isSet: isSet, value: hour) } /* replace this HourButton(id: "\(project.shortname)\(0)", isSet: isSet, value: listOfPossibleHours[0]) HourButton(id: "\(project.shortname)\(1)", isSet: isSet, value: listOfPossibleHours[1]) // What do you expect with \(0) */ Text("\(project.leftPMtime)") .font(.custom("Menlo", size: 16)) // <<-- To get proper alignment Spacer() // <<-- ADDED } } } struct HourButton: View,Identifiable { var id: String = "hour" @State var isSet: Bool var value: Double = 1 var body: some View { HStack { Button { isSet.toggle() print("clic already \(isSet) \(id)h & \(value) has Value") } label: { Label("8h", systemImage: isSet ? "circle.fill" : "circle") .labelStyle(.iconOnly) .foregroundStyle(isSet ? .blue : .gray) }.id(id) } } } struct TimeKeyinList: View, Identifiable { var id: String = "" // to ease test var projects = [ Project(name: "Project1, isTeco = false, shortname = MORN, leftPMTime = 131",shortname : "MORN", leftPMtime : 131, isTeco: false), Project(name: "Project2, isTeco = false, shortname = MORN, leftPMTime = 122",shortname : "IFF", leftPMtime : 122, isTeco: true), Project(name: "Project3, isTeco = false, shortname = MORN, leftPMTime = 133",shortname : "FFI", leftPMtime : 133, isTeco: true), Project(name: "Project4, isTeco = false, shortname = MORN, leftPMTime = 444",shortname : "IFFCO", leftPMtime : 444, isTeco: false) ] @State var isSet: [Bool] = [true, false, false, true] @State private var hideTeco = false var filteredProjects: [Project] { // removeTECO project projects.filter { project in !project.isTeco }} var body: some View { VStack { ForEach(Array(filteredProjects.enumerated()), id: \.offset) { (row, project) in TimeKeyInRow(id: project.shortname, project: project, isSet: $isSet[row]) } } .labelsHidden() .onAppear() { // <<-- Added for (row, project) in filteredProjects.enumerated() { isSet[row] = !project.isTeco } } } } struct Project: Identifiable { var id: UUID = UUID() var name: String var shortname: String var leftPMtime: Int var isTeco: Bool } Note: What is isTeco meaning ? In some cases, neither shortName not isTeco match with label: Project(name: "Project2, isTeco = false, shortname = MORN, leftPMTime = 122",shortname : "IFF", leftPMtime : 122, isTeco: true), Is it on purpose ?
Topic: UI Frameworks SubTopic: SwiftUI Tags:
Feb ’24
Reply to Creating an Array/Button with specific ID everybutiton regardless of projectName or Hours
It's a bit hard to track your code, but let's try. In TimeKeyinList, you have a single var: @State var isSet: Bool And in the loop, you use it for every TimeKeyInRow ForEach (filteredProjects) { project in TimeKeyInRow(id: project.shortname, project: project, isSet: $isSet) So, logically, when you change for one, you change for all. The state var should be an array of Bool indexed by row or a dictionary, the key being the project.id and the value isSet. Something like (I let you test): struct TimeKeyinList: View, Identifiable { @State var isSet: [Bool] and the loop: ForEach(Array(filteredProjects.enumerated()), id: \.offset) { (row, project) in TimeKeyInRow(id: project.shortname, project: project, isSet: $isSet[row]) Or with dictionary: @State var isSet: [String:Bool] and the loop: ForEach (filteredProjects) { project in TimeKeyInRow(id: project.shortname, project: project, isSet: $isSet[project.id] ?? false) If that works, don't forget to close the thread by marking the answer as correct. Otherwise, explain what's the problem.
Topic: UI Frameworks SubTopic: SwiftUI Tags:
Feb ’24
Reply to Timing of CollectionView layouts
It is whatever information will help analyse your problem. Not your words of what the problem is, but the elements that may help find the root cause. For instance, the storyboard layout (a screenshot of the view will help) and the constraints you've defined…
Topic: Programming Languages SubTopic: Swift Tags:
Feb ’24
Reply to Swift Charts Won't Update a Variable Value
So ChartView is a SwiftUI view ? What is the State var or the Observable that is updated when you log something, so that the UI is updated ? You should provide more code of Chart View. Also; have a look at this TN: https://developer.apple.com/documentation/swiftui/migrating-from-the-observable-object-protocol-to-the-observable-macro
Feb ’24
Reply to Restricting the App Playground to iPhones in Portrait Mode
how to restrict my app playground to run on iPhones only If you want to submit your app for the student challenge, answer is No. App will be tested either on Mac or iPad. Not on iPhone: https://letvar.medium.com/ten-years-later-why-you-should-try-the-swift-student-challenge-b32de6cd29b6 The application process, step by step: … Answer the questions about how the judges should run the Playground (either macOS or iPadOS)
Feb ’24