TabBar SwiftUI 2.0 中其他视图的键盘调用 OnAppear

Mal*_*oni 9 keyboard uitabbarcontroller tabview swift swiftui

我在 SwiftUI 2.0 和 Xcode 12 中使用 UITabBarController,但似乎键盘盒出现了一些意外行为。正如您从下面的 GIF 中看到的,当键盘出现在第一个选项卡中时,调用了其他 2 个选项卡视图的 OnAppear。这导致了这个问题,因为我有一个写在上面的 API 调用出现。

另外,有什么方法可以关闭 Xcode 12 的默认视图偏移行为。

在此处输入图片说明

这是我的内容视图代码。

struct ContentView: View {
    @State private var index:Int = 0
    var menuItems:[String] = ["Item 1", "Item 2", "Item 3"]
    var body: some View {
        NavigationView(content: {
            ZStack{
                MyTabView(selectedIndex: self.$index)
                    .view(item: self.item1) {
                        NewView(title: "Hello1").navigationBarTitle("")
                            .navigationBarHidden(true)
                    }
                    .view(item: self.item2) {
                        NewView(title: "Hello2").navigationBarTitle("")
                            .navigationBarHidden(true)
                    }
                    .view(item: self.item3) {
                        NewView(title: "Hello3").navigationBarTitle("")
                            .navigationBarHidden(true)
                    }
            }.navigationBarHidden(true)
            .navigationBarTitle("")
        })
    }
    
    var item1:MyTabItem {
        
        var item = MyTabItem()
        item.imageName = "pencil.circle"
        item.selectedImageName = "pencil.circle.fill"
        return item
    }
    
    var item2:MyTabItem {
        var item = MyTabItem()
        item.imageName = "pencil.circle"
        item.selectedImageName = "pencil.circle.fill"
        return item
    }
    
    var item3:MyTabItem {
        var item = MyTabItem()
        item.imageName = "pencil.circle"
        item.selectedImageName = "pencil.circle.fill"
        return item
    }
}


struct NewView:View {
    @State var text:String = ""
    var title:String
    var body: some View {
        VStack {
            Spacer()
            Text("Hello")
            TextField(title, text: self.$text)
                .textFieldStyle(RoundedBorderTextFieldStyle())
            
        }.padding()
        .onAppear {
            debugPrint("OnApper \(self.title)")
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

这是 CustomTabView 的代码。

class MyTabViewViewModel:ObservableObject {
    var controllers: [UIViewController] = []
    var tabItems:[MyTabItem] = []
}

struct MyTabItem {
    var imageName:String = ""
    var selectedImageName:String = ""
    var hasDarkModeSupport:Bool = true
    var image:UIImage?
    var selectedImage:UIImage?
}

struct MyTabView: UIViewControllerRepresentable {
    
    var viewModel:MyTabViewViewModel = MyTabViewViewModel()
    
    @Binding var selectedIndex: Int
    
    func makeUIViewController(context: Context) -> UITabBarController {
        let tabBarController = UITabBarController()
        tabBarController.viewControllers = self.viewModel.controllers
        tabBarController.delegate = context.coordinator
        tabBarController.selectedIndex = 0
        
        let appearance = tabBarController.tabBar.standardAppearance
        appearance.shadowImage = nil
        appearance.shadowColor = nil
        appearance.backgroundEffect = nil
        tabBarController.tabBar.standardAppearance = appearance
        
        tabBarController.tabBar.shadowImage = UIImage()
        tabBarController.tabBar.backgroundImage = UIImage()
        tabBarController.tabBar.layer.shadowPath = UIBezierPath(rect: tabBarController.tabBar.bounds).cgPath
        tabBarController.tabBar.layer.shadowOffset = CGSize.init(width: 0, height: -3)
        tabBarController.tabBar.layer.shadowRadius = 5
        tabBarController.tabBar.layer.shadowColor = UIColor.black.cgColor
        tabBarController.tabBar.layer.shadowOpacity = 0.25
        tabBarController.tabBar.backgroundColor = UIColor.white
        tabBarController.tabBar.barTintColor = UIColor.white
        
        self.updateTabItems(forTabBarController: tabBarController)
        
        return tabBarController
    }
    
    func updateUIViewController(_ tabBarController: UITabBarController, context: Context) {
        tabBarController.selectedIndex = selectedIndex
        self.updateTabItems(forTabBarController: tabBarController)
    }
    
    func makeCoordinator() -> Coordinator {
        Coordinator(self)
    }
    
    func updateTabItems(forTabBarController tabBarController:UITabBarController) {
        let isDarkModeEnable:Bool = tabBarController.traitCollection.userInterfaceStyle == .dark
        for (index, tabItem) in self.viewModel.tabItems.enumerated() {
            
            tabBarController.tabBar.items?[index].title = ""
            
            if let image = tabItem.image {
                tabBarController.tabBar.items?[index].image = image
                if let selectedImage = tabItem.selectedImage {
                    tabBarController.tabBar.items?[index].selectedImage = selectedImage
                }
            } else {
                if tabItem.hasDarkModeSupport && isDarkModeEnable {
                    if let image = UIImage.init(systemName: "\(tabItem.imageName)-dark") {
                        tabBarController.tabBar.items?[index].image = image
                    } else if let image = UIImage.init(systemName: tabItem.imageName) {
                        tabBarController.tabBar.items?[index].image = image
                    }
                    if let selectedImage = UIImage.init(systemName: "\(tabItem.selectedImageName)-dark") {
                        tabBarController.tabBar.items?[index].selectedImage = selectedImage
                    } else if let selectedImage = UIImage.init(systemName: tabItem.selectedImageName) {
                        tabBarController.tabBar.items?[index].selectedImage = selectedImage
                    }
                } else {
                    if let image = UIImage.init(systemName: tabItem.imageName) {
                        tabBarController.tabBar.items?[index].image = image
                    }
                    if let selectedImage = UIImage.init(systemName: tabItem.selectedImageName) {
                        tabBarController.tabBar.items?[index].selectedImage = selectedImage
                    }
                }
            }
        }
    }
    
    class Coordinator: NSObject, UITabBarControllerDelegate {
        var parent: MyTabView
        
        init(_ tabBarController: MyTabView) {
            self.parent = tabBarController
        }
        
        func tabBarController(_ tabBarController: UITabBarController, didSelect viewController: UIViewController) {
            parent.selectedIndex = tabBarController.selectedIndex
        }
    }
    
    func view<HostedView:View>(item:MyTabItem, @ViewBuilder sheet: @escaping () -> HostedView) -> MyTabView {
        self.viewModel.controllers.append(UIHostingController.init(rootView: sheet()))
        self.viewModel.tabItems.append(item)
        return self
    }
}
Run Code Online (Sandbox Code Playgroud)

小智 1

我自己也有同样的问题

“Hackish”解决方法是将其包装NewView.body在列表中:

    @State var text:String = ""
    var title:String
    var body: some View {
        List {
            VStack {
                Spacer()
                Text("Hello")
                TextField(title, text: self.$text)
                    .textFieldStyle(RoundedBorderTextFieldStyle())
                
            }.padding()
            .onAppear {
                debugPrint("OnApper \(self.title)")
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

也可以使用 a LazyVStack,但还没有测试它,因为我的项目目标是 13.x

同样的问题,当键盘出现在 SwiftUI 中时,OnAppear 会意外调用