为啥 SwiftUI 模态视图在此处更新父变量(附代码)

Posted

技术标签:

【中文标题】为啥 SwiftUI 模态视图在此处更新父变量(附代码)【英文标题】:why is SwiftUI modal view updating parent variable here (code attached)为什么 SwiftUI 模态视图在此处更新父变量(附代码) 【发布时间】:2020-04-06 20:08:21 【问题描述】:

在下面的代码中,如果我更改 TextField 的值,然后单击“取消”(即不会保存 coredata),隐藏此模式视图后,父 UI 列表中的值是否会更改?

这条线是否有效地通过了我的参考?如果是,如何通过价值有效地改变?

更新:实际上,保存按钮中的代码似乎是在取消按钮中的代码之后直接调用的,即在我单击取消的情况下。不知道为什么会这样?

代码:

import SwiftUI

struct GCListsViewEdit: View 
    @Environment (\.presentationMode) var presentationMode
    @State var titleStr : String = ""
    var gcItem : GCList?

    var body: some View 
        NavigationView 
            Form 
                Section(header: Text("Enter Details")) 
                    TextField("List Title", text: self.$titleStr)
                        .onAppear 
                            self.titleStr = self.gcItem?.title ?? ""  // ** HERE **
                        
                
                HStack 
                    Button("Cancel") 
                        self.presentationMode.wrappedValue.dismiss()
                    
                    Spacer()
                    Button("Save") 
                        guard !self.titleStr.isEmpty else 
                            return
                        
                        guard let item = self.gcItem else 
                            return
                        
                        item.title = self.titleStr
                        GCCoreData.save()
                        self.presentationMode.wrappedValue.dismiss()
                    
                
            
            .navigationBarTitle("Edit List")
        
    

PARENT - 只是身体部分

var body : some View 
    NavigationView 
        VStack 

            // -- Main List  --
            List() 
                ForEach(gcLists)  gcList in
                    HStack 
                        if self.editMode 
                            Button(action: ) 
                              Text("\(gcList.title)")
                            
                            .onTapGesture 
                                self.selectedListViewItem = gcList
                                self.newListItemTitle = gcList.title
                                self.showEditView.toggle()
                            
                            .sheet(isPresented: self.$showEditView, content: 
                                GCListsViewEdit(gcItem: self.selectedListViewItem!)
                            )
                         else 
                            NavigationLink(destination: GCTasksView(withGcList: gcList)) 
                                Text("\(gcList.title)")
                            
                        
                    
                
                .onDelete(perform: self.deleteList)
                .onMove(perform: self.move)

            
            .environment(\.editMode, editMode ? .constant(.active) : .constant(.inactive))
            .alert(isPresented: $showingAlert) 
                Alert(
                    title: Text(verbatim: "Important Message"),
                    message: Text(self.alertString),
                    dismissButton: Alert.Button.default(Text(verbatim: "Cancel"))
                )
            
            .navigationBarTitle( Text("Todo Lists") )
            .navigationBarItems(
                trailing: Button(action: 
                    print("Edit" as Any)
                    self.editMode = !self.editMode
                 ) 
                    Text(editMode ? "Done" : "Edit")
                
            )

            // -- Add List Item ---selectedListViewItem
            Button("Add List") 
                self.newListItemTitle = ""
                self.showAddView.toggle()
            
            .sheet(isPresented: $showAddView, content:  GCListsViewAdd()  )

        
    

【问题讨论】:

你是如何实现父级的? 刚刚添加到父级的正文部分——这就够了吗? 所以你的问题是当你关闭编辑视图时,“self.selectedListViewItem”会更新吗? 是的,当我点击取消时 更新:实际上看起来保存按钮中的代码在取消按钮中的代码之后直接被调用,即在我单击取消的情况下。不知道为什么会发生这种情况? 【参考方案1】:

Form 类似于ListList 对一行中的标准按钮进行特定处理 - 它使整行处于活动状态,因此当在任何位置点击行时,一个按钮(或多个按钮)被激活。

在您的示例中,即使您在之间点击取消和保存,这两个操作都会执行。

有几种可能的解决方案:

1) 使用点击手势(保留按钮或将其替换为其他视图、文本、图像等),例如


HStack 
    Button("Cancel") 
    .onTapGesture 
        print(">> do cancel")
    
    Spacer()
    Button("Save") 
    .onTapGesture 
        print(">> do save")
    


2) 使用自定义按钮样式,因为List 只拦截DefaultButtonStyle 按钮

struct CustomButton: ButtonStyle 
    func makeBody(configuration: Self.Configuration) -> some View 
        configuration.label
            .foregroundColor(configuration.isPressed ? Color.gray : Color.blue)
        


HStack 
    Button("Cancel") 
        print(">> do cancel")
    .buttonStyle(CustomButton())
    Spacer()
    Button("Save") 
        print(">> do save")
    .buttonStyle(CustomButton())


3) 将此屏幕的按钮移出Form(例如在NavigationBar 中)

【讨论】:

非常感谢 - Form 是否会根据某些视图来划分“行”,对吗?所以一个 HStack 似乎必须划定一行......

以上是关于为啥 SwiftUI 模态视图在此处更新父变量(附代码)的主要内容,如果未能解决你的问题,请参考以下文章

SwiftUI 模态演示在 iPad 模拟上搞砸了?

为啥我的 UIView 子视图没有在父视图中呈现? (附代码)

SwiftUI @Binding 未在子项中更新

为啥可观察对象中的更新变量不会更新视图?

为啥我的 SwiftUI 视图不会在更新 @State var 时更新?

SwiftUI ObservedObject 不更新父视图