Home > Software design >  how to update struct variable when swiped in TabView
how to update struct variable when swiped in TabView

Time:01-31

I want to record long term, how many times a specific ItemView has been displayed in my TabView below. Each time a user swipes on the tab, I want to update var timesViewed by 1. However, timesViewed doesn't seem to update and I am really stuck as to why now. I am a SwitUI noob, so thanks for the patience!

I removed some view modifiers to simplify the code below.

struct Item: Identifiable, Hashable, Codable {
    var id = UUID()
    var title: String
    var detail: String
    var repeatOn: String
    var timesViewed = 0
    
    mutating func viewedThisItem() {
        timesViewed  = 1
    }
}

struct ItemSessionView: View {
    var itemViewModel: ItemListVM
    @State var count = 0
    @State var currentIndex = 0
    
    
    var body: some View {
        let today = getTodaysDate().uppercased()
        var tempList = itemViewModel.list.filter({ return $0.repeatOn == today})
        ZStack {
            GeometryReader { proxy in
                TabView(selection: $currentIndex) {
                    ForEach(tempList) { item in
                        Group {
                            if today == item.repeatOn {
                                ItemDetailView(item: item)
                            }
                        }
                    }
                }
                .onChange(of: currentIndex) { value in
                    tempList[currentIndex].viewedThisItem()
                }
            }
        }
    }

    
    func getTodaysDate() -> String {
        let today = Date.now
        let formatter = DateFormatter()
        formatter.dateStyle = .short
        formatter.timeStyle = .medium
        formatter.dateFormat = "E"
        let todaysDate = formatter.string(from: today)
        
        return todaysDate
    }
}

CodePudding user response:

Structs are value type, you modify the (copied) item in the filtered array but not the original item in the itemViewModel object.

A possible solution is to get the item in the itemViewModel object by id and modify that directly.

.onChange(of: currentIndex) { value in
    let id = tempList[value].id
    let index = itemViewModel.list.firstIndex{$0.id == id}!
    itemViewModel.list[index].viewedThisItem()
}

Force unwrapping is safe because the item does exist.

  • Related