0

我想要实现的目标:我是一名新的 SwiftUI 开发人员。我正在尝试构建一个简单的地址簿应用程序。我有三个观点:

  1. ContentView - 包含列表视图中所有联系人的主视图,在导航视图顶部带有添加联系人 ('+') 和编辑按钮
  2. AddContact 视图 - 具有“名称”和“电子邮件”文本字段以及“提交”按钮
  3. DisplayContactDetails 视图 - 与此问题无关。

我创建了一个环境对象“myContacts”,它是一个“联系人”对象数组,并将它传递到 ContentView 以跟踪通讯簿中的所有联系人

当用户导航到 AddContact 视图、添加姓名和电子邮件并提交时,我希望更新环境对象“myContacts”并将用户导航回 ContentView,以便他们可以看到包含新联系人的通讯簿包括。

问题

当用户在 AddContact View 上按下“提交”时,它会正确调用我创建的导航链接以将用户发送回 ContentView。但是因为环境对象“myContacts”也被提交更新了,它会立即再次从 ContentView 导航回 AddContact View。因此,它似乎首先执行导航链接,然后由于 myContacts 的刷新而重新加载 AddContact 视图。

代码 - 内容视图

    struct ContentView: View {
    
    @EnvironmentObject var myContacts: Contacts
    @State var isAddButtonPressed: Bool = false
    
    var body: some View {
        
        NavigationView{
           
            List {
                
                ForEach(myContacts.contacts) { item in
                    
                    NavigationLink(
                          //Display items and send user to DisplayContactDetails

                        })
                    
                }
            
            }
            .navigationBarTitle("Address Book")
            .toolbar {
                ToolbarItem(placement: .navigationBarLeading){
                    
                    Button(action: {
                        isAddButtonPressed.toggle()
                    }, label: {
                        
                       NavigationLink(
                        destination: AddContactView(),
                        isActive: $isAddButtonPressed,
                        label: {
                            Image(systemName: "plus")
                        })
                        
                    })
                }
                ToolbarItem(placement: .navigationBarTrailing){
                    EditButton()
                }
                
                
            }
        }
    }
    
}

代码 - AddContactView

struct AddContactView: View {
    
    @State var name: String = ""
    @State var email: String = ""
    @State var isButtonPressed: Bool = false
    
    @EnvironmentObject var myContacts: Contacts
    
    var body: some View {
        
       
        VStack{
            
            HStack{
                Text("Name:")
                TextField("Enter name", text: $name)
            }
            .padding(.bottom, 50)
            
            HStack{
                Text("Email:")
                TextField("Enter email", text: $email)
            }
            .padding(.bottom, 50)
            
            
            Button("Submit") {
                
                let contactToAdd = Contact(name: name, email: email)
                
                //Add is a simple function - all it does is append an item to the    myContacts array using the .append method
                myContacts.add(contact: contactToAdd)
                isButtonPressed = true
            }

            .frame(width: 80, height: 30, alignment:.center)
            .background(Color.blue)
            .foregroundColor(.white)
            .clipShape(Capsule())
                
            NavigationLink(destination: ContentView().navigationBarHidden(true),
                    isActive: $isButtonPressed,
                    label: {
                       EmptyView()
                    }).hidden()
            
        }.padding()
            
        }
    
}

我试过的

如果我注释掉 .add 方法并且不更新环境对象,则导航回 ContentView 将按预期工作。所以我知道这具体是问题的原因。

我尝试将 .onTapGesture 修饰符添加到 Button 并在那里调用 .add 。

我尝试将 .onDisappear 修饰符添加到整个视图并在那里调用 .add 。

- 任何有关解决此问题的帮助或澄清将不胜感激

编辑:屏幕录制 - 根据第一条评论尝试解决方案:

当我尝试解决方案时会发生什么

奇怪的行为:第一次尝试添加联系人自动路由回 AddContactView,产生相同的错误。但是,如果我再次尝试它,那么它会正确路由到 ContactView。

4

1 回答 1

0

编辑更新。这是我用来测试我的答案的代码:

import SwiftUI

@main
struct TestApp: App {
    @StateObject var myContacts = Contacts()
    var body: some Scene {
        WindowGroup {
            ContentView().environmentObject(myContacts)
        }
    }
}

struct Contact: Identifiable {
    var id = UUID()
    var name: String = ""
    var email: String = ""
}

class Contacts: ObservableObject {
    @Published var contacts: [Contact] = [Contact(name: "name1", email: "email1"), Contact(name: "name2", email: "email2")]
    
    func add(contact: Contact) {
        contacts.append(contact)
    }
}

struct AddContactView: View {
    @Environment(\.presentationMode) private var presentationMode
    
    @EnvironmentObject var myContacts: Contacts
    
    @State var name: String = ""
    @State var email: String = ""

    var body: some View {
        VStack{
            HStack{
                Text("Name:")
                TextField("Enter name", text: $name)
            }
            .padding(.bottom, 50)
            HStack{
                Text("Email:")
                TextField("Enter email", text: $email)
            }
            .padding(.bottom, 50)
            Button("Submit") {
                let contactToAdd = Contact(name: name, email: email)
                myContacts.add(contact: contactToAdd)
                presentationMode.wrappedValue.dismiss()
            }
            .frame(width: 80, height: 30, alignment:.center)
            .background(Color.blue)
            .foregroundColor(.white)
            .clipShape(Capsule())
        }.padding()
    }
}

struct ContentView: View {
    @EnvironmentObject var myContacts: Contacts
    @State var isAddButtonPressed: Bool = false
    
    var body: some View {
        NavigationView {
            List {
                ForEach(myContacts.contacts) { item in
                    NavigationLink(destination: AddContactView()) {
                        Text(item.name)
                    }
                }
            }
            .navigationBarTitle("Address Book")
            .toolbar {
                ToolbarItem(placement: .navigationBarLeading){
                    Button(action: {
                        isAddButtonPressed.toggle()
                    }, label: {
                        NavigationLink(
                            destination: AddContactView(),
                            isActive: $isAddButtonPressed,
                            label: {
                            Image(systemName: "plus")
                        })
                    })
                }
                ToolbarItem(placement: .navigationBarTrailing){
                    EditButton()
                }
            }
        }
    }
}
于 2021-07-08T10:22:23.600 回答