【问题标题】:SwiftUI @State and .sheet() ios13 vs ios14SwiftUI @State 和 .sheet() ios13 与 ios14
【发布时间】:2021-01-04 20:54:29
【问题描述】:

您好,我在这里遇到了问题,在 ios13 或 ios14 上运行时,我的 .sheet() 视图之间的行为不一致

我有这样的看法:

@State private var label: String = "" 
@State private var sheetDisplayed = false
///Some code
var body: some View {
   VStack {
      Button(action: {
         self.label = "A label"
         self.isDisplayed = true
      }) {
           Text("test")
       }
   }.sheet(isPresented: $sheetDisplayed, onDismiss: {
        self.label = ""
    }) {
        Text(self.label)
       }
 }

在 ios 13 上按预期工作 btn 单击 -> 设置标签 -> 调用表 -> 在文本视图中显示“A 标签”。

在 ios14 上,当我关闭工作表时,self.label 中有一个空字符串,因此它不显示任何内容。

我错过了什么吗?是 iOS 14 的错误还是我在 ios13 上的错误并已得到纠正。

PS:我在闭包中传递了几个其他变量,我对其进行了简化。

【问题讨论】:

  • 看起来工作表是在您设置标签之前创建的。您不应该依赖 SwiftUI 创建视图的顺序,但在这种情况下,我认为这是一个值得提交给 Apple 的错误。
  • 同样的事情发生在 iOS 15 中。
  • 感谢您的评论。如果您遇到问题,请检查接受的答案我仍然在 ios 15 上工作

标签: swiftui ios13 ios14


【解决方案1】:

您的代码期望视图更新/创建顺序,但通常它是未定义的(并且可能在 iOS 14 中更改)。

有明确的方式在工作表内传递信息 - 使用不同的工作表创建者,即。 .sheet(item:...

这是一个可靠的例子。使用 Xcode 12 / iOS 14 测试

struct ContentView: View {
    @State private var item: Item?

    struct Item: Identifiable {
        let id = UUID()
        var label: String = ""
    }

    var body: some View {
        VStack {
            Button(action: {
                self.item = Item(label: "A label")
            }) {
                Text("test")
            }
        }.sheet(item: $item, onDismiss: {
            self.item = nil
        }) {
            Text($0.label)
        }
    }
}

【讨论】:

  • 我能够使用您的解决方案使其工作 谢谢。但奇怪的是,当添加 didSet 道具观察者和打印值(或在调试中)时,我的值在进入该工作表内容关闭之前确实发生了变化,并且工作表中仍然有 nil。
【解决方案2】:

这是 iOS 14 中的一些非常奇怪的行为,似乎没有记录。

在这里使用other answerthis thread 上的评论,我使用@Binding 来解决问题,因为它似乎是最干净和最符合SwiftUI-esq 的解决方案。

我不知道为什么这种行为发生了变化,而且它看起来不像以前那么直观,所以我假设它是一个错误!

一个例子:

struct MainView: View {
    @State private var message = ""
    @State private var showSheet = false

    var body: some View {
        Button(action: {
            self.message = "This will display the correct message"
            self.showSheet = true
        }, label: {
            Text("Test Button")
        })
        .sheet(isPresented: self.$showSheet) {
            SheetView(message: self.$message)
        }
    }
}

struct SheetView: View {
    @Binding var message: Int

    var body: some View {
        Text(self.message)
    }
}

【讨论】:

  • 感谢您的更新,我已经有几天没有看那个帖子了,但我记得我试过这个没有成功(至少在我的情况下,我过度简化了我的问题在这里)但是我有一个在我的工作表关闭中为零的选项,导致应用程序崩溃。
  • 你能解释一下,为什么你需要通过Binding?为什么只传递一个包装的值不起作用?我在我的代码中测试了解决方案并添加了魔法$ 并在稍后解开该值就可以了......
  • 我猜是因为工作表能够修改绑定的值,所以它需要是一个绑定,因为普通值/引用对象将在父视图中丢失。此外, sheet() 构造函数需要它(或者 isPresented: Binding 或 item:Binding 请参阅此处以供参考developer.apple.com/documentation/swiftui/view/…
【解决方案3】:

SwiftUI 2.0 的行为发生了变化,因此它也影响了 MacOS 11,只需向视图添加一个绑定即可修复它,即使该绑定从未使用过,这让我认为这是一个实现错误。 此外,仅在视图主体内的 Text() 中使用 details 状态变量也可以修复它。

struct MyViewController : View {

    @State var details: String?
    @State var showDetails = false

    //    @Binding var havingAbindingFixesIt: String?

    var body: some View {
        VStack {
            //            Text(details ?? "")
            Text("Tap here for details")
                .onTapGesture {
                    self.details = "These are the details"
                    self.showDetails.toggle()
                }
                .sheet(isPresented: $showDetails) { Text(details ?? "") }
        }
    }
}

【讨论】:

    猜你喜欢
    • 2021-01-03
    • 1970-01-01
    • 2021-04-18
    • 1970-01-01
    • 2021-11-30
    • 2019-11-10
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多