【问题标题】:OnAppear calls unexpectedly when Keyboard Appears in SwiftUISwiftUI 中出现键盘时 OnAppear 意外调用
【发布时间】:2021-01-09 15:02:46
【问题描述】:

我在 SwiftUI 2.0 和 iOS14 中遇到了非常奇怪的行为。

当键盘出现在屏幕上时,自动调用其他标签视图的OnAppear方法。

但是,这在 Xcode 11.7 中运行良好

这是正在发生的问题。

这是产生上述错误的代码。

struct ContentView: View {
    var body: some View {
        TabView {
            DemoView(screenName: "Home")
                .tabItem {
                    Image.init(systemName: "star.fill")
                    Text("Home")
                }
            DemoView(screenName: "Result")
                .tabItem {
                    Image.init(systemName: "star.fill")
                    Text("Result")
                }
            DemoView(screenName: "More")
                .tabItem {
                    Image.init(systemName: "star.fill")
                    Text("More")
                }
        }
    }
}

struct DemoView:View {
    
    @State var text:String = ""
    var screenName:String
    var body: some View {
        VStack{
            Text(screenName)
                .font(.title)
            
            TextField("Buggy Keyboard Issue", text: $text)
                .textFieldStyle(RoundedBorderTextFieldStyle())
                
            Text("Issue : When keyboard appears, onAppear of other 2 tabs call automatically.")
                .font(.footnote)
        }
        .padding()
        .onAppear(perform: {
            debugPrint("OnAppear of : \(screenName)")
        })
    }
}

这似乎是 SwiftUI 2.0 的错误,但不确定。 任何帮助将不胜感激。

谢谢

【问题讨论】:

  • 我已经向 Apple 报告了这种行为。 feedbackassistant.apple.com/feedback/8732425
  • SwiftUI onAppear 不等于 UIKit viewDidAppear。 一旦视图在视图层次结构中呈现,它们就会调用 onAppear(而不是当它对用户可见时)。何时、为什么以及调用多少次是完全不同的问题,实际上并没有在任何地方指定/记录,所以我不会依赖这种行为,因为它是从一个版本到另一个版本的变化。
  • 不。你有过同样的经历吗?
  • 是的,我有:/ .
  • 对我来说同样的问题!。如果我们不能依赖onAppear,当视图可见时我们应该在哪里进行网络调用。

标签: keyboard swiftui textfield tabview swiftui-tabview


【解决方案1】:

我自己也有同样的问题,我认为这是一个错误或类似的问题,但是我想出了一个解决方案,也许是一种解决方法,直到苹果修复它。

我所做的事情基本上是我使用了LazyVStack,这似乎工作得很好。

LazyVStack {
    VStack{
        Text(screenName)
            .font(.title)
        
        TextField("Buggy Keyboard Issue", text: $text)
            .textFieldStyle(RoundedBorderTextFieldStyle())
            
        Text("Issue : When keyboard appears, onAppear of other 2 tabs call automatically.")
            .font(.footnote)
    }
    .padding()
    .onAppear(perform: {
        debugPrint("OnAppear of : \(screenName)")
})
}

现在其他选项卡视图的OnAppear方法在键盘出现时不会自动调用。

【讨论】:

  • lazyvstack 在这里做了什么?
  • 对我有用。我认为当键盘出现时其他选项卡视图会重新加载。当键盘出现在另一个选项卡中时,lazyvstack 导致视图不会重新加载。
  • 这可行,但有潜在问题
【解决方案2】:

刚刚实施了以下解决方法:

struct ContentView: View {
    var body: some View {
        TabView(selection: $selectedTab) {
            TabContentView(tag: 0, selectedTag: selectedTab) {
                Text("Some tab content")
            }
            .tabItem {
                Text("First tab")
            }
            TabContentView(tag: 0, selectedTag: selectedTab) {
                Text("Another tab content")
            }
            .tabItem {
                Text("Second tab")
            }
        }
    }
    
    @State private var selectedTab: Int = 0
}

private struct TabContentView<Content: View, Tag: Hashable>: View {
    init(tag: Tag, selectedTag: Tag, @ViewBuilder content: @escaping () -> Content) {
        self.tag = tag
        self.selectedTag = selectedTag
        self.content = content
    }

    var body: some View {
        Group {
            if tag == selectedTag {
                content()
                    .frame(maxWidth: .infinity, maxHeight: .infinity)
            } else {
                Color.clear
            }
        }
        .tag(tag)
    }

    private let tag: Tag
    private let selectedTag: Tag
    private let content: () -> Content
}

不确定它是否足够稳定,但键盘外观不再在标签内容上触发onAppear

【讨论】:

    【解决方案3】:

    为避免重新加载视图,请尝试在 TabView 上

    .ignoresSafeArea(.keyboard, edges: .bottom)
    

    它仅适用于 iOS 14

    【讨论】:

    • 这对我不起作用,赏金要点中显示了实现
    • 这不行,这是 SwiftUI 中的一个错误 我向 Apple 提交了反馈但尚未得到回复:FB8646389,实际上这个错误在我的代码中产生了很多意外行为
    • 我也无法正常工作
    猜你喜欢
    • 2021-01-05
    • 2022-01-19
    • 1970-01-01
    • 2020-11-14
    • 1970-01-01
    • 1970-01-01
    • 2021-08-04
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多