In the Apple's SwiftUI tutorial 'Scrumdinger', the ScrumTimer
model publishes three properties, and the speakers
property is not included.
class ScrumTimer: ObservableObject {
/// The name of the meeting attendee who is speaking.
@Published var activeSpeaker = ""
/// The number of seconds since the beginning of the meeting.
@Published var secondsElapsed = 0
/// The number of seconds until all attendees have had a turn to speak.
@Published var secondsRemaining = 0
/// NOTE: This property is not published.
private(set) var speakers: [Speaker] = []
}
But when we click the 'next' button in the MeetingView
, the MeetingFooterView
gets redrawn.
struct MeetingView: View {
@Binding var scrum: DailyScrum
@StateObject var scrumTimer = ScrumTimer()
private var player: AVPlayer { AVPlayer.sharedDingPlayer }
var body: some View {
ZStack {
RoundedRectangle(cornerRadius: 16)
.fill(scrum.theme.mainColor)
VStack {
MeetingHeaderView(secondsElapsed: scrumTimer.secondsElapsed, secondsRemaining: scrumTimer.secondsRemaining, theme: scrum.theme)
Circle()
.strokeBorder(lineWidth: 24)
MeetingFooterView(speakers: scrumTimer.speakers, skipAction: scrumTimer.skipSpeaker)
// DebugView(speakers: scrumTimer.speakers)
}
}
.padding()
.foregroundColor(scrum.theme.accentColor)
.onAppear {
print("### .onAppear() run")
scrumTimer.reset(lengthInMinutes: scrum.lengthInMinutes, attendees: scrum.attendees)
scrumTimer.speakerChangedAction = {
player.seek(to: .zero)
player.play()
}
scrumTimer.startScrum()
}
.onDisappear {
scrumTimer.stopScrum()
}
.navigationBarTitleDisplayMode(.inline)
}
}
The question is: the MeetingFooterView
depends on scrumTimer.speakers
, which is an unpublished property, how does it decides to redraw based on whether scrumTimer.speakers
has changed?
The complete code can be fetched here.
Thank you.