【问题标题】:Why is it in SwiftUI, when presenting modal view with .sheet, init() is called twice为什么在 SwiftUI 中,当使用 .sheet 呈现模态视图时,init() 被调用了两次
【发布时间】:2020-02-20 08:10:22
【问题描述】:

我正在使用以下代码在 WatchOS 上生成情况

struct Modal : View {
    @Binding var showingModal : Bool
    
    init(showingModal : Binding<Bool>){
        self._showingModal = showingModal
        print("init modal")
    }
    
    var body: some View {
        Button(action: {
            self.showingModal.toggle()
        }, label: {
            Text("TTTT")
        })
    }
}

struct ContentView: View {
    @State var showingModal = false
    var body: some View {
        Button(action: {
            self.showingModal.toggle()
        }, label: {
            Text("AAAA")
        }).sheet(isPresented: $showingModal, content: {Modal(showingModal: self.$showingModal)})
    }
}

每次我在主视图中按下按钮以调用带有 .sheet 的模态时,都会创建模态视图的两个实例。

谁能解释一下这个现象?

【问题讨论】:

  • 它似乎与动画正在进行时的过渡有关)。你有什么问题吗?不能保证任何时候都不会重新创建 View,即使在 iOS 或 macOS 上也是如此。只是不要担心,不要依赖 SwiftUI 的工作方式。状态相关的表示,这是唯一可以遵循的范式。

标签: ios swift iphone swiftui


【解决方案1】:

我在我的代码中跟踪到在我的视图中有以下行:

@Environment(\.presentationMode) var presentation

由于https://stackoverflow.com/a/61311279/155186,我一直在这样做,但由于某种原因,这个问题似乎对我来说已经消失了,所以我想我不再需要它了。

我已就此向 Apple 提交反馈 FB7723767。

【讨论】:

    【解决方案2】:

    这可能是一个错误,从 Xcode 11.4.1 (11E503a) 开始。 请注意,例如,如果像这样初始化视图模型(或其他任何东西):

    .sheet(isPresented: $isEditingModalPresented) {
        LEditView(vm: LEditViewModel(), isPresented: self.$isEditingModalPresented)
    }
    

    虚拟机将被初始化两次。

    【讨论】:

    • 我也在 Xcode 11.6 上遇到了这个错误。我尝试从按钮操作中设置值。这没有调用 .sheet 两次,但是在该类内的 ObservableObject 视图模型上设置相同的布尔值会导致它触发两次。所以,我在 1 秒后调度到主队列,它只调用一次。如果您调度 0.5,它会被调用两次。这确实是一种非常奇怪的行为,但我发现这是一种目前可行的解决方法。
    【解决方案3】:

    从 Modal 中注释掉/删除 init() 方法,其他一切都相同。您应该能够解决创建两个 Modal 实例的问题,这是因为您在 Modal 的 init() 中显式地初始化了绑定(showingModal)。希望这是有道理的。

    【讨论】:

    • 我只是测试一下。我在 Modal 中注释了 init() 并在其下附加了一个成员 obj(成员 obj 在 init() 时打印出来)。模态似乎仍在创建两次。
    • 对不起,我似乎误解了这个问题。我做了一些实验,发现即使有两个调用通过 init() 也只有一个表实例化。这可能是 SwiftUI 中的一个错误。我通过 .onAppear(){print("OnAppear")} 对模态按钮进行了测试。你会发现两行打印了“init modal”,但一行打印了“OnAppear”。
    【解决方案4】:
    private let uniqueId: String = "uniqueId" 
    
    Button(action: {
        self.showingModal.toggle()
    }, label: {
        Text("AAAA")
    })
        .sheet(isPresented: $showingModal) {
            Modal(showingModal: self.$showingModal)
              .id("some-unique-id")
        }
    

    例如:

    .id(self.uniqueId)

    为您的 .sheet 添加唯一 ID,不用担心 :)

    But, do not use UUID(), because sheet view will be represented on every touch event

    【讨论】:

      猜你喜欢
      • 2013-11-20
      • 2019-10-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-03-28
      • 1970-01-01
      • 2012-04-23
      相关资源
      最近更新 更多