在 SwiftUI 中,如何在 XcodePreview 中设置 editMode 的环境变量

Posted

技术标签:

【中文标题】在 SwiftUI 中,如何在 XcodePreview 中设置 editMode 的环境变量【英文标题】:In SwiftUI how do I set the environment variable of editMode in an XcodePreview 【发布时间】:2019-07-07 15:06:56 【问题描述】:

给定这样的导航堆栈层次结构,其中编辑按钮被添加到另一个源文件中

struct ContentView : View 
  var body: some View 
    NavigationView 
      EditingView()
    .navigationBarItems(trailing: EditButton())

  

使用编辑按钮的视图在代码库的其他地方

struct EditingView : View 

  @State var dataValue: String = "Initial Value"
  @Environment(\.editMode) var editMode

    var body: some View 
      VStack(alignment: .leading) 
        if self.editMode?.value == .inactive 
          Text(dataValue)
         else 
          TextField(($dataValue))
        
      .padding()
        .navigationBarTitle("Lets edit some State")
        .navigationBarItems(trailing: EditButton())
  

能否以编程方式在预览中设置初始编辑模式?有没有办法在没有编辑按钮的情况下使用环境查看 EditingView?我发现工作的几种方法显示在 sn-p 中,但我希望我能找到一种方法来通过环境以编程方式设置和初始值。

#if DEBUG
struct EditingView_Previews : PreviewProvider 
  static var previews: some View 
    NavigationView 
      VStack 
        EditingView()

        // I would prefer to use an environment variable.
        // Here is the best thought at some code:
        //
        //   `.environment(\.editMode, .inactive)`
        //
        // the compiler Error returned:
        // Type 'Binding<EditMode>?' has no member 'inactive'
        //
        // which I understand since it is a binding
        // not a direct access to an enum variable.
        // But can I set it somehow or should I let the system
        // handle it entirely?

        // So to get around the issue I have an extra edit button
        EditButton()

      
    
  
  // Or this could work
  //.navigationBarItems(trailing: EditButton())

#endif

可以在此处找到示例项目: https://github.com/PaulWoodIII/PreviewEditMode

【问题讨论】:

作为记录,Binding 可以使用.constant(value) 代替实际值初始化为常量。所以.environment(\.editMode, .constant(.inactive)) 可以设置环境变量。 【参考方案1】:

您可以通过添加到您的预览提供程序将其作为常量传递:

.environment(\.editMode, Binding.constant(EditMode.active))

例如:

struct EditingView_Previews : PreviewProvider 
  static var previews: some View 
    NavigationView 
      EditingView()
      
    
    .environment(\.editMode, Binding.constant(EditMode.active))
  


【讨论】:

这在我的视图检查条件 self.editMode?.wrappedValue == .active 时有效,但在使用内置 List 视图时无效。【参考方案2】:

环境变量editMode 是一个绑定。您可以通过编程方式进行设置,例如:

struct outerView: View 
    @State var editMode: EditMode = .active

    var body: some View 
        return InnerView(model: model).environment(\.editMode, $editMode)
    

【讨论】:

【参考方案3】:

我发现当有NavigationView 时“EditMode”不起作用,但我没有找到任何文档提及。 以下代码运行良好

struct ContentView: View 
    @Environment(\.editMode)  var mode

    var body: some View 
        HStack 
            if self.mode?.wrappedValue == .active 
                Button("Cancel") 
                    self.mode?.animation().wrappedValue = .inactive
                
            

            Spacer()
            EditButton()
        
        


但是有NavigationView的时候就不行了

struct ContentView: View 
    @Environment(\.editMode)  var mode

    var body: some View 
        NavigationView 
            HStack 
                if self.mode?.wrappedValue == .active 
                    Button("Cancel") 
                        self.mode?.animation().wrappedValue = .inactive
                    
                

                Spacer()
                EditButton()
            
        
    

【讨论】:

【参考方案4】:

这并不能解决能够设置EditMode 的环境值的问题,我也很想知道该怎么做,但更好的解决方法是在您的视图后面隐藏EditButton正在预览:

struct ProfileHost_Previews : PreviewProvider 
    static var previews: some View 
        ZStack 
            EditButton().hidden()
            ProfileHost()
        
    

假设您正在预览的视图已经具有切换编辑模式的方法,例如EditButton

【讨论】:

以上是关于在 SwiftUI 中,如何在 XcodePreview 中设置 editMode 的环境变量的主要内容,如果未能解决你的问题,请参考以下文章

如何在 SwiftUI 中停止 Animation().repeatForever

如何使用 SwiftUI 在 UICollectionViewCell 中填充内容

如何在 SwiftUI 的 ScrollView 中制作动画? SwiftUI 中的手风琴风格动画

如何在 SwiftUI 中使用 SFSafariViewController?

如何在 SwiftUI 中激活/停用菜单项

如何在 SwiftUI 中居中裁剪图像