5

GIF of Entire Screen Refreshing

I am currently learning combine and MVVM. My problem is when I try to use a timer.publish, eventually I'm going to create a stop button, it causes the entire screen to refresh instead of the Text I have .onReceive.

I was hoping someone could provide me some insight on how I'm using publishers and observers incorrectly.

View:

import SwiftUI
import Combine

struct ApptCardView: View {

    @ObservedObject var apptCardVM: ApptCardViewModel
    @State var currentDate = Date()
    let timer = Timer.publish(every: 1, on: .main, in: .common).autoconnect()

    var body: some View {
        VStack {
            Text("\(currentDate)")
                .onReceive(timer) { input in
                    self.currentDate = input
                   }
            Picker("Seizure Type", selection: $apptCardVM.typeIndex) {
            ForEach(0..<apptCardVM.typeChoice.count) {
                Text(self.apptCardVM.typeChoice[$0])
            }
        }.pickerStyle(SegmentedPickerStyle())

        }

    }
}

View Model:

import Foundation
import Combine


class ApptCardViewModel: ObservableObject, Identifiable {

    @Published var appt: ApptEvent
    @Published var typeChoice = ["Quick", "Long", "FullService"]
    @Published var typeIndex: Int = 0



    private var cancellables = Set<AnyCancellable>()

    init(appt: ApptEvent) {
        self.appt = appt
    }

}
Zeimin
  • 53
  • 4

1 Answers1

2

If you want to refresh only a part of body, then separate that part into dedicated subview, eg:

struct ApptCardView: View {

    @ObservedObject var apptCardVM: ApptCardViewModel

    var body: some View {
        VStack {
            CurrentDateView()  // << here !!

            Picker("Seizure Type", selection: $apptCardVM.typeIndex) {
            ForEach(0..<apptCardVM.typeChoice.count) {
                Text(self.apptCardVM.typeChoice[$0])
            }
        }.pickerStyle(SegmentedPickerStyle())

        }

    }
}

struct CurrentDateView: View {
    @State private var currentDate = Date()
    let timer = Timer.publish(every: 1, on: .main, in: .common).autoconnect()
    var body: some View {
        Text("\(currentDate)")
            .onReceive(timer) { input in
                self.currentDate = input // << refresh only own body !!
        }
    }
}
Asperi
  • 228,894
  • 20
  • 464
  • 690