【问题标题】:State variable value is being lost状态变量值正在丢失
【发布时间】:2021-01-11 00:52:54
【问题描述】:

我在 ios 1 中运行以下代码。当按下“视图 A”按钮时,状态变量 nextModalView2 设置为 NextModalView2.a 但是当执行 Sheet() 调用时,nextModalView2 的值被重置为 .none .

这怎么可能?

此外,如果您查看屏幕截图,您会看到调试器控制台面板显示的 nextModalView2 值与调试器变量面板中显示的值不同。怎么样?


enum NextModalView2{
  case none
  case a
  case b
}

struct Menu2: View {
  @State private var isShowModally = false
  @State private var nextModalView2 = NextModalView2.none

  var body: some View {
    VStack(alignment: .center) {
      Button(action: {
        self.isShowModally = true
        self.nextModalView2 = .a
        print("self.nextModalView = \(self.nextModalView2)")
      }){ Text("View A")
      }
      Divider()
      Button(action: {
        self.isShowModally = true
        self.nextModalView2 = .b
      }){ Text("View B")
      }
      .padding(.top, 20)
    }
    .sheet(isPresented:  $isShowModally){
      Group{
        if self.nextModalView2 == .a {
          //        case NextModalView2.a:
          AnyView(Text("A"))
        }
        if  self.nextModalView2 == NextModalView2.b{
          AnyView(Text("B"))
        }
        if self.nextModalView2 == NextModalView2.none{
          AnyView(EmptyView())
        }
      }
    }
  }
}

【问题讨论】:

  • 当您的视图出现在屏幕上时,会配置 .sheet() 修饰符。所以在 init() 上,.sheet() 将返回 .none。解决方案是避免在工作表关闭中打开内容。我在这里为此提供了 2 个超级简单的解决方案:stackoverflow.com/questions/65416673/…

标签: swiftui


【解决方案1】:

我们需要在这种情况下使用sheet(item: 修饰符,它适用于每个选择。

这里有一个解决方案。使用 Xcode 12.1 / iOS 14.1 测试。

enum NextModalView2: Identifiable{
    var id: NextModalView2 { self }
    case none
    case a
    case b
}

struct Menu2: View {
    @State private var nextModalView2: NextModalView2?
    
    var body: some View {
        VStack(alignment: .center) {
            Button(action: {
                self.nextModalView2 = .a
                print("self.nextModalView = \(self.nextModalView2 ?? .none)")
            }){ Text("View A")
            }
            Divider()
            Button(action: {
                self.nextModalView2 = .b
            }){ Text("View B")
            }
            .padding(.top, 20)
        }
        .sheet(item: $nextModalView2){ item in
            switch item {
            case .a:
                Text("A")
            case .b:
                Text("B")
            default:
                EmptyView()
            }
        }
    }
}

【讨论】:

  • 这似乎是一个不错的解决方案。关于为什么调试器变量面板没有显示正确的属性值的任何想法(如控制台调试器中正确显示的那样?
【解决方案2】:

我在 SwiftUI 中使用工作表的经验是,您可以获得一些非常有趣的行为(尤其是在 Catalyst 上)。我的怀疑是工作表在第一次运行时被渲染(当你的值是 none 时),然后当你的 @State 变量发生变化时实际上并没有被调用来更新,可能是因为在幕后,工作表是包裹在 UIViewControllerRepresentable 之类的东西中,当你认为它们会传递时,值并没有传递。

我提取了您的工作表视图并将参数更改为@Binding,即使您可能不需要双向通信,因为它似乎可以解决此问题:


enum NextModalView2 {
  case none
  case a
  case b
}

struct ContentView: View {
  @State private var isShowModally = false
  @State private var nextModalView2 = NextModalView2.none
    
  var body: some View {
    VStack(alignment: .center) {
      Button(action: {
        self.nextModalView2 = .a
        self.isShowModally = true
        print("self.nextModalView = \(self.nextModalView2)")
      }){ Text("View A")
      }
      Divider()
      Button(action: {
        self.nextModalView2 = .b
        self.isShowModally = true
      }){ Text("View B")
      }
      .padding(.top, 20)
    }
    .sheet(isPresented:  $isShowModally){
        SheetContent(nextModalView2: $nextModalView2)
    }
  }
}

struct SheetContent : View {
    @Binding var nextModalView2 : NextModalView2
    
    var body: some View {
        Group{
          if self.nextModalView2 == .a {
            AnyView(Text("A"))
          }
          if  self.nextModalView2 == NextModalView2.b{
            AnyView(Text("B"))
          }
          if self.nextModalView2 == NextModalView2.none {
            AnyView(EmptyView())
          }
        }
    }
}

【讨论】:

    猜你喜欢
    • 2011-05-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-07-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多