Meu problema é que, quando edito um modelo, a interface do usuário em BeginWorkoutView não atualiza corretamente. Acredito que estou usando @ObservableObject/@Published/@Mainactor incorretamente, mas não consigo descobrir como. Todos os tutoriais parecem usar o padrão que estou usando atualmente, e funciona para eles.
Tenho uma página principal, BeginWorkoutView. Nela, você pode criar um novo treino ou criar modelos de treino. Você também pode ver todos os modelos criados e clicar para editá-los.
aqui está uma versão simplificada disso:
struct BeginWorkoutView: View {
@ObservedObject var templateManager = TemplateManager.shared
var body: some View {
NavigationView{
ScrollView{
Section("Start from scratch"){
HStack{
NavigationLink("New Workout"){
//new workout page
}
NavigationLink("New Template"){
CreateTemplateView( viewModel: CreateTemplateViewModel(), editMode: true)
}
}
}
Section("Start from template") {
ForEach(templateManager.templates, id: \.id.self) { template in
TemplateRowView(template: template)
}
}
}
}
}
}
Gerencio meus dados em um gerenciador de modelos. Consigo adicionar novos treinos e eles aparecem na minha página BeginWorkoutView sem problemas. Como eu disse, quando edito o título, ele não é atualizado na BeginWorkoutView. Pelo que posso perceber, a lista de modelos do templateManager ESTÁ sendo atualizada, mas isso não parece acionar a interface do usuário. Atualmente, estou usando a estrutura de objeto @mainactor/@Observable porque quero oferecer suporte a versões anteriores ao iOS 17.
@MainActor
final class TemplateManager: ObservableObject {
@Published private(set) var templates: [WorkoutTemplate] = []
static let shared = TemplateManager()
init(){
getTemplates()
}
func getTemplates() {
//gets templates from firebase
}
func updateTemplates(template: WorkoutTemplate) {
Task{
do {
//updates templates in firebase
//HERE is where the UI should be getting the signal to update. Obviously spot replacing the template didnt work, but replacing the entire thing wont work either.
var updated = templates
if let index = updated.firstIndex(where: { $0.id == template.id }) {
updated[index] = template
} else {
updated.append(template)
}
self.templates = updated
} catch {
print("unable to update templates")
}
}
}
}
Seja criando um novo modelo ou editando um, eu uso createtemplateview/createtemplateviewmodel. Aqui estão versões simplificadas, basicamente apenas com as chamadas de função. Não acredito que o problema esteja aqui, mas estou adicionando-as caso sejam úteis.
@MainActor
final class CreateTemplateViewModel: ObservableObject {
@Published var template: WorkoutTemplate
var templateManager = TemplateManager.shared
init(template: WorkoutTemplate) {
self.template = template
}
init(){
self.template = WorkoutTemplate(name: "Workout Template", workoutModules: [])
}
func addTemplateList() {
templateManager.updateTemplates(template: template)
}
func removeTemplateList() {
templateManager.removeTemplateList(templateId: template.id)
}
}
struct CreateTemplateView: View {
@StateObject var viewModel: CreateTemplateViewModel
var body: some View {
ScrollView{
StringTextField(preview: "Template Name", $viewModel.template.name )
.padding()
//shows editable modules for the template
Button("save"){
viewModel.addTemplateList()
}
}
}
}
Existem "truques" por aí, como usar notificações ou combinar para notificar a interface do usuário para atualização, mas acredito que isso deve funcionar se feito corretamente. Estou escrevendo isso principalmente para aprender essas estruturas de dados e estou com dificuldade para entender isso, então definitivamente gostaria de chegar ao fundo da questão em vez de aplicar uma correção paliativa.