Post

Replies

Boosts

Views

Activity

Reply to Swiftui - Pressing button in a list also actions another button
You have to set buttonStyle (does not work with default value), such as: .buttonStyle(.borderless) // Or some other style So your code: List(am.students) { item in HStack { Text(item.name).font(fancyFont) Spacer() Button(item.casual ? "All Paid" : "Reverse All Paid") { // Issue: pressing this button also results in Remove button action being invoked. item.casual = !item.casual } .buttonStyle(.borderless) // <<-- ADD THIS Or some other style .foregroundColor(Color(white: 0.15)) .padding(3) .overlay( RoundedRectangle(cornerRadius: 5) .stroke(Color(white: 0.5), lineWidth: 3) ) Spacer().frame(width: 40) Button("Remove") { Task { await am.delete(student: item) } } .buttonStyle(.borderless) // <<-- ADD THIS Or some other style .foregroundColor(Color(white: 0.15)) .frame(width: 80) .padding(3) .overlay( RoundedRectangle(cornerRadius: 5) .stroke(Color(white: 0.5), lineWidth: 3) ) } }
Topic: UI Frameworks SubTopic: SwiftUI Tags:
May ’24
Reply to How might I get didSet behaviour on an AppStorage var?
Surprising. I tested the code proposed here and it works: https://stackoverflow.com/questions/63171806/willset-not-being-called-on-swiftuis-new-appstorage-property struct DemoAppStorageDidSet: View { @AppStorage("codeResult") var codeResult: String = "Default" { // << default value willSet { print("willSet: \(newValue)") } didSet { print("didSet: \(oldValue)") } } var body: some View { VStack { Text("Code Result: \(codeResult)") Divider() Button("AppStore Update") { self.codeResult = "AppStore" // << activates willSet/didSet !! } Divider() Button("UserDefaults Update") { UserDefaults.standard.set("UserDefaults", forKey: "codeResult") } } } }   Tapping "AppStore Update" logs as expected: willSet: AppStore didSet: Default Tapping a second time: willSet: AppStore didSet: AppStore So please show your complete code that does not work (maybe stupid question: are you sure the console is visible for log ?)
Topic: UI Frameworks SubTopic: SwiftUI Tags:
May ’24
Reply to FORM PROBLEMS
That's a limit of SwiftUI: a view cannot have more than 10 subviews (here sections). There is a workaround: group up to 10 sections in a Group Form { Group { Section { } Section { } // up to 10 sections } Group { Section { } Section { } // up to 10 sections } }
Topic: UI Frameworks SubTopic: SwiftUI Tags:
May ’24
Reply to SF Symbol
Where did you see this symbol ? In an Apple's app or another app ? I searched also for circle and for dotted. Could not find it either. moon.circle is relatively close to this. But not the same.
Topic: Design SubTopic: General Tags:
May ’24
Reply to Swift: Can I change views without clicking on a link.
I would try it differently: struct ContentView: View { //#if os(iOS) // var myOS = "iOS" //#elseif os(OSX) // var myOS = "OSX" //#else // var myOS = "Something Else" //#endif struct ScreenIOS: View { var body: some View { VStack { Text("Welcome iOS !") } } } struct ScreenMacOS: View { var body: some View { VStack { Text("Welcome MacOS !") } } } var body: some View { NavigationStack { VStack { Text("PLEASE WAIT …") // Wait do you wait for ? .font(.system(size: 24)) .fontWeight(.bold) } .padding() if ProcessInfo.processInfo.isiOSAppOnMac { // if (myOS == "OSX") { ScreenMacOS() // Goto Screen for iMac } else { ScreenIOS() // go to screen for iOS } } } }
Topic: UI Frameworks SubTopic: SwiftUI Tags:
May ’24
Reply to Question about textfield
What @darkpaw said, plus: Are you sure you have set the delegate for A, B (and C eventually). I tested your code and it works as is as soon as delegate is set to the ViewController. Note: fields names should start with lowercase.
Topic: UI Frameworks SubTopic: SwiftUI Tags:
May ’24
Reply to IBOutlet becomes nil after ViewController is initialized
Does this crash your app or is it working OK ? Is the IBOutlet declared weak (as it should be) ? Do you get the warning: Instance will be immediately deallocated because property "selectButton" is weak AFAIU, the storyboard adds var it to the view and the view then gets a strong reference to it. Found interesting discussion here: https://stackoverflow.com/questions/51437935/xcode-10-uibutton-custom-deallocated-property-is-weak-in-swift-4 old one: https://forums.swift.org/t/instance-will-be-immediately-deallocated-warning-in-xcode-when-using-weak-property/16596/6
Topic: Programming Languages SubTopic: Swift Tags:
May ’24
Reply to Swift UI TabView selection binding strange behaviour ?
Not an explanation (I am interested to read an "authorised" analysis, but my understanding is that calling onChange on the State var, leads TabView to reevaluate its content. Why ? That is the question ! A possible reason: as oldValue, newValue change, that forces the TabView to redraw (and reevaluate). Generally, I have noticed it is very hard (and hazardous) to try to guess how SwiftUI works to reevaluate views…
Topic: UI Frameworks SubTopic: SwiftUI Tags:
May ’24
Reply to Is it true that @State is used for Value types and @StateObject is used for Reference types?
That used to be true until recently. With the Observable() it is no more true. From StateObject doc: If you need to store a value type, like a structure, string, or integer, use the State property wrapper instead. Also use State if you need to store a reference type that conforms to the Observable() protocol. To learn more about Observation in SwiftUI, see Managing model data in your app.
Topic: UI Frameworks SubTopic: SwiftUI Tags:
May ’24
Reply to Editable hierarchical list in runtime
I was puzzled by the crash when removing an added item. That had to do with the focus on the TextField… This works more properly: struct FileItem: Identifiable { var name: String var children: [FileItem]? // 👈🏻 Will be nil if child at lowest level of hierarchy ; otherwise for parent, should be [] when no child var id: String { name } } struct ContentView: View { @State var data: [FileItem] = [ FileItem(name: "First", children: [FileItem(name: "childF1"), FileItem(name: "childF2")]), FileItem(name: "Second", children: [FileItem(name: "childS1"), FileItem(name: "childS2"), FileItem(name: "childS3")]), FileItem(name: "Third", children: [FileItem(name: "childT1"), FileItem(name: "childT2")]) ] @FocusState private var focusedField: String? var body: some View { List($data, children: \.children) { $item in HStack { TextField("", text: $item.name) // probleme : le clavier disparait à chaque caractère // Avec focused, on passe au dernier TextField .focused($focusedField, equals: item.name) .task { self.focusedField = item.name } // If there are no children, we cannot remove it if item.children != nil { // So it is parent, maybe with no child [] Spacer() Button("Add child") { // let's search its position in data for (index, parent) in data.enumerated() { if parent.name == item.name && parent.children != nil { // double check on nil let childrenCount = parent.children!.count var newChildName = "new child \(childrenCount+1)" for child in parent.children! { // let's not give the same name twice if newChildName == child.name { newChildName = "new child \(childrenCount+100)" } } data[index].children!.append(FileItem(name: newChildName)) } } } .foregroundColor(.green) .buttonStyle(.borderless) } Spacer() Button("Remove") { // This is a simple implementation if only children, no grandChildren // if grandchildren, need to have a recursive search for the parent self.focusedField = nil var deleteDone = false DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) { // <<-- To give time to update focus for (index, individual) in data.enumerated() { // remove child if deleteDone { print("I quit loop") ; break } if !deleteDone { if individual.children != nil && !individual.children!.isEmpty { for child in individual.children! { if child.name == item.name { var newChildren = individual.children! newChildren.removeAll(where: { $0.name == item.name }) data[index].children = newChildren deleteDone = true break } } } // remove parent if !deleteDone { for (index, individual) in data.enumerated() { if individual.name == item.name { data.remove(at: index) deleteDone = true break } } } } } } .foregroundColor(.red) .buttonStyle(.borderless) } } } }
Topic: UI Frameworks SubTopic: SwiftUI Tags:
May ’24
Reply to Editable hierarchical list in runtime
When you add on child line, what do you add ? A child of the parent ? A child of the child ?   I need to have both for each line item. So simple! Remove some tests. Here is an updated code… struct ContentView: View { @State var data: [FileItem] = [ FileItem(name: "First", children: [FileItem(name: "childF1"), FileItem(name: "childF2")]), FileItem(name: "Second", children: [FileItem(name: "childS1"), FileItem(name: "childS2"), FileItem(name: "childS3")]), FileItem(name: "Third", children: [FileItem(name: "childT1"), FileItem(name: "childT2")]), ] @FocusState private var focusedField: String? var body: some View { List($data, children: \.children) { $item in HStack { TextField("", text: $item.name) .focused($focusedField, equals: item.name) // avoid keyboard to disappear at each character .task { self.focusedField = item.name } // Text(item.name) // If there are no children, we cannot remove it if item.children != nil { // So it is parent, maybe with no child [] Spacer() Button("Add child") { // let's search its position in data print("added") for (index, parent) in data.enumerated() { if parent.name == item.name && parent.children != nil { // double check on nil data[index].children!.append(FileItem(name: "new child")) } } } .buttonStyle(.borderless) } // if item.children == nil || item.children!.isEmpty { // nil when item is child, empty for parent Spacer() Button("Remove") { // This is a simple implementation if only children, no grandChildren // if grandchildren, need to have a recursive search for the parent var deleteDone = false for (index, individual) in data.enumerated() { // remove child if !deleteDone { if individual.children != nil && !individual.children!.isEmpty { for child in individual.children! { if child.name == item.name { var newChildren = individual.children! newChildren.removeAll(where: { $0.name == item.name }) data[index].children = newChildren deleteDone = true break } } } } // REMOVE THIS -> else { // remove parent if !deleteDone { for (index, individual) in data.enumerated() { if individual.name == item.name { data.remove(at: index) deleteDone = true break } } } // } } } .buttonStyle(.borderless) // } } } } } There are still some tuning to be done (error when removing an added child). But that should give you a start point. As I explained, if you want more levels, you can use the same struct and List. But you will have to write the function to search for an item in the hierarchy in order to add or remove it in the data. That's a good exercise.
Topic: UI Frameworks SubTopic: SwiftUI Tags:
May ’24