Post

Replies

Boosts

Views

Activity

Not sure how to add Prev/Next buttons in my SwiftUI List's Detail view.
I have a SwiftUI app with a List displaying an array of model objects. When the user taps a list item we see its detail view. I want to add previous and next buttons to my detail view, but I'm not sure what needs to happen when previous/next are tapped. (see code below for what I'm looking to do) My first thought is to make the model variable in the DetailView be a binding, but I'm not sure how this would tie in with the NavigationLink 'stuff' any/all suggestions appreciated. thanks! class Model: Identifiable {     var modelValue: Int     init(modelValue: Int) {         self.modelValue = modelValue     }     static let testData = [Model(modelValue: 3), Model(modelValue: 7), Model(modelValue: 31)] } class ModelManager {     static let shared = ModelManager()     let modelList = Model.testData     func previous(for model: Model) - Model? {         if let index = modelList.firstIndex(where: {$0.modelValue == model.modelValue}) {             if index 0 {                 return modelList[index - 1]             }         }         return nil     }     func next(for model: Model) - Model? {         if let index = modelList.firstIndex(where: {$0.modelValue == model.modelValue}) {             if index modelList.count - 1  {                 return modelList[index + 1]             }         }         return nil     } } struct ContentView: View {     let manager:ModelManager = ModelManager.shared     var body: some View {         NavigationView {             List(manager.modelList) { object in                 NavigationLink(                     destination: DetailView(model: object, previous: manager.previous(for: object), next: manager.next(for: object)),                     label: {                         Text("fred \(object.modelValue)")                     })             }         }     } } struct DetailView: View {     var model: Model     var previous: Model?     var next: Model?     var body: some View {         VStack {             HStack {                 if previous != nil {                     Button("Previous") {                         // goto previous                     }                 }                 Spacer()                 if next != nil {                     Button("Next") {                         // goto next                     }                 }             }             Text("value: \(model.modelValue)")             Spacer()         }     } }
1
0
1.6k
Mar ’21
Having problems with a SwiftUI checkbox binding I'm implementing...
Hello folks, I'm attempting to implement some swiftUI UI code to support filtering of a list. One part of the filtering involves displaying one checkbox for each case/value of an enum (TangleType below) TangleFilter is a model class that includes an array of TangleTypeFilter objects (each owning a single bool value and a binding) Expected behaviour: when user taps a checkbox, the checkbox toggles the display and the filter model object toggles its value. Actual behaviour: the model is updating appropriately, however the UI is not updating. (the single filter below the list does in fact behave correctly any and all guidance greatly appreciated Mike struct ContentView: View {     @State var isChecked: Bool = false     @ObservedObject var filter = TangleFilter()     @ObservedObject var singleFilter: TangleTypeFilter     init() {         self.singleFilter = TangleTypeFilter(tangleType: .grid)     }     var body: some View {         VStack{             List(filter.tangleTypes, id: \.self) {tangleTypeFilter in                 HStack {                     // when uncommented the following line returns the following                     // compile error:                     // Use of unresolved identifier '$tangleTypeFilter' //                    CheckBox(isChecked: $tangleTypeFilter.isChecked)                     CheckBox(isChecked: tangleTypeFilter.binding)                     Text("checked? \(tangleTypeFilter.isChecked.description)")                 }             }             CheckBox(isChecked: $singleFilter.isChecked)         }     } } struct CheckBox: View {     @Binding var isChecked: Bool {         didSet {             print("setting isChecked: \(isChecked)")         }     }     var imageName: String {         return isChecked ? "checkmark.square" : "square"     }     var body: some View {         Button(action: {             self.isChecked.toggle()         }) {             Image(systemName: self.imageName)         }     } } enum TangleType: String, Codable, CaseIterable {     static let filterArray: [TangleTypeFilter] = {         var result: [TangleTypeFilter] = []         for tangleType in TangleType.allCases {             result.append(TangleTypeFilter(tangleType: tangleType))         }         return result     }()     case grid     case row } class TangleFilter: ObservableObject {     @Published var tangleTypes: [TangleTypeFilter] = TangleType.filterArray } class TangleTypeFilter: ObservableObject {     var tangleType: TangleType     @Published var isChecked: Bool     lazy var binding: Binding<Bool> = Binding(get: {         return self.isChecked     }, set: {         self.isChecked = $0     })     init(tangleType: TangleType) {         self.tangleType = tangleType         self.isChecked = false     } } extension TangleTypeFilter: Hashable {     static func == (lhs: TangleTypeFilter, rhs: TangleTypeFilter) -> Bool {         return lhs.tangleType == rhs.tangleType     }     func hash(into hasher: inout Hasher) {         hasher.combine(tangleType)     } }
6
1
2.9k
Jan ’21
A potentially dumb questions about swift (and dateFormatters)
I seem to recall hearing that DateFormatters are (or were) expensive to instantiate. With this in mind, I tried a small experiment with the following code: class MyClass { &#9;&#9;static let df = DrawingCellView.dateFormatter     static var dateFormatter: DateFormatter {         let result = DateFormatter()         result.dateFormat = "yyyy-MM-dd"         return result     } &#9;&#9;func dateText() -> String { &#9;&#9;&#9;&#9;return MyClass.dateFormatter.string(from: Date()) &#9;&#9;} When I put a breakpoint in the dateFormatter code, it fires each time I use it. However if I instead use df, the breakpoint only fires once. Does this make sense? If so, is this the recommended way to construct a runOnce static constant declaration/assignment? thanks! Mike
2
0
686
Jan ’21