import SwiftUI class Player: Identifiable, ObservableObject { let id = UUID() @Published var name: String @Published var counterLog = [ CounterLogEntry() ] init(name: String) { self.name = name } } class CounterLogEntry: Identifiable { let id = UUID() @State var title = "" @State var count = 0 } class CountingViewModel: ObservableObject { let player: Player init(player: Player) { self.player = player } func addNewEntry() { player.counterLog.append(CounterLogEntry()) } func removeEntry(entry: CounterLogEntry) { player.counterLog.removeAll(where: { e in e.id == entry.id }) } } struct CountingView: View { @ObservedObject var viewModel: CountingViewModel @Environment(\.presentationMode) var presentationMode init(player: Player) { viewModel = CountingViewModel(player: player) } var body: some View { List { Section(header: Text("\(NSLocalizedString("counting.title", comment: "")) \(viewModel.player.name)")) { if viewModel.player.counterLog.count > 0 { ForEach(viewModel.player.counterLog, id: \.id) { entry in VStack { TextField("counting.titlePlaceholder", text: entry.$title) HStack { Button(action: { entry.count += 1 }) { HStack { Text("+") .font(.headline) .fontWeight(.black) .foregroundColor(Color.white) .padding(EdgeInsets(top: 12, leading: 32, bottom: 12, trailing: 32)) } } .background(Color.green) .cornerRadius(10) .padding(.leading, 4) .padding(.trailing, 4) Spacer() Text("\(entry.count)") .font(.system(.title)) .fontWeight(.black) Spacer() Button(action: { entry.count -= 1 }) { HStack { Text("-") .font(.headline) .fontWeight(.black) .foregroundColor(Color.white) .padding(EdgeInsets(top: 12, leading: 32, bottom: 12, trailing: 32)) } } .background(Color.red) .cornerRadius(10) .padding(.leading, 4) .padding(.trailing, 4) } } .padding(.top, 8) .padding(.bottom, 8) } } else { Text("log.noEntries") .font(.system(.subheadline)) .fontWeight(.bold) .frame(maxWidth: .infinity, alignment: .center) .padding(.top, 32) .padding(.bottom, 32) } } Section() { Button(action: { self.viewModel.addNewEntry() }) { HStack { Spacer() Text("counting.addEntry") .font(.headline) .foregroundColor(Color.white) Spacer() } } } .listRowBackground(Color.green) Section() { Button(action: { self.presentationMode.wrappedValue.dismiss() }) { HStack { Spacer() Text("close") .font(.headline) .foregroundColor(Color.white) Spacer() } } } .listRowBackground(Color.red) } .listStyle(GroupedListStyle()) .environment(\.horizontalSizeClass, .regular) } } struct CountingView_Previews: PreviewProvider { static var previews: some View { let firstLogEntry = CounterLogEntry() firstLogEntry.title = "Lorem ipsum dalor sit amet" firstLogEntry.count = 1024 let player = Player(name: "DEBUG") player.counterLog = [ firstLogEntry, CounterLogEntry() ] return CountingView(player: player) } }