SwiftUI 添加一个 UISearchBar 到导航栏

SwiftUI adding a UISearchBar to the navigation bar

所以我对 SwiftUI 比较陌生,我正在尝试将 UISearchBar 添加到我的导航栏中,但我无法让它显示出来。如果我将它添加为一个单独的组件,它会出现,但它离屏幕太远了。这是我目前所拥有的:

UISearchBar 组件:

struct SearchBar2: UIViewRepresentable {
    @Binding var text: String
    func makeUIView(context: Context) -> UISearchBar {
        let searchbar = UISearchBar(frame: .zero)
        return searchbar
    }
    
    func updateUIView(_ uiView: UISearchBar, context: Context) {
        uiView.text = text
    }
    
}

UIView:

var body: some View{
      
        
        ZStack{
        
        NavigationView{
        VStack {
            NavigationLink()                                    
            {
                InitView()
            }.buttonStyle(PlainButtonStyle())
            ZStack {
                HStack {
                    //some items here
                }
            }.toolbar{
                SearchBar2(text: $text)
            }
            DayView()
        }
        
    }
                
        }
        
    }

这是模拟器上的样子: Screenshot

好的,既然你是一名学生,我想提供一些重要的反馈,并为你提供成功所需的工具。

关键反馈

  • 首先,请永远记住,当您开始以开发人员的身份从事专业工作时,您不需要无所不知。事实上,如果您的雇主确实希望如此,运行。此作业的重点是让您批判性地思考解决方案并将其分解为最小的部分。

我是如何找到解决方案的

  • 首先我评估了问题并考虑了解决方案,SwiftUI 中最简单的解决方案是不使用 UISearchBar,但我意识到您的需求需要它,这对于真实情况来说是非常真实的世界运作。很多时候,在工作中,你会遇到一个简单的解决方案的挑战,你会被要求以一种不简单的方式来做,但你必须那样做。

  • 一旦我有了要求,我就查看了修饰符 .toolBar(...)。原来它需要 ToolbarItem(..)。我需要更多的信息;然而,我是循着踪迹找到它的。我了解到 ToolbarItem(...) 接受 some View。这意味着我们可以将任何我们想要的东西放入其中。您可以放置​​图像、搜索栏、文本字符串或其他任何内容。我还了解到,您可以更改 placement: 的构造函数中的参数,它有几个选项,包括 .bottom.principal,如果您将工具栏放在顶部或底部,这很有用.对于此解决方案,我使用 .principal

    放置它
    NavigationLink(destination: Text("Some Link")) {
          Text("Button Text")
      }.toolbar {
          ToolbarItem(placement: .principal) {
              SearchBar2(text: $sampleText)
          }
      }
    

我遇到的问题

  • 我遇到的第一个问题,如果你复制这段代码,你很快就会发现,SearchBar2(...) 将出现在第一个 NavigationView 上,如果那是你的位置想要它,太棒了,但我怀疑您可能想要在“呈现视图”上使用它,这是开始理解的一项重要技能。

导航速成班

  • 工具栏出现在第一页上而不是导航到的页面上的原因是因为它是在第一页上构建的。您可能会问自己,“我怎样才能让它出现在第二页上?”

  • 要让它出现在第二页,您只需将 ToolbarItem(...) 移动到第二页,通常在根视图上作为修饰符。这样做的原因是可以在构建视图本身时构建它。

  • 从字面上看,NavigationView 就像一堆卡片,当您从一张卡片转到另一张卡片时,“后面”的卡片会被抓住,前面的卡片会在您开始导航时创建。这再次非常重要,因为如果您向后导航,然后尝试再次前进,如果视图被破坏,您将丢失数据,或者 Swifty 术语 deInit(...)。有大量选项可用于保存该数据并在以后恢复它,例如 @AppStorageUserDefaults.

  • 演示这个视图构造、解构难题的一个有用方法是看看这段代码,在 运行 之前,问问自己会发生什么?注意 .toolBar(...) 被添加到根 Text(...) 那么它会出现在第一个视图还是第二个视图中?

    NavigationView {
         NavigationLink(destination: Text("Some Link")) {
             Text("Button Text")
                 .toolbar {
                     ToolbarItem(placement: .principal) {
                         SearchBar2(text: $sampleText)
                     }
                 }
         }
     }
    
  • 答案是它将再次出现在第一个视图中。你可能会问,“为什么?”这是因为 Text(...) 是在第一个视图以及所有关联的修饰符上构建的。然而,如果我们将工具栏作为修饰符添加到第二个视图,SearchBar2 将出现在那里。

    struct ContentView: View {
      @State var sampleText = ""
    
      var body: some View {
          NavigationView {
              NavigationLink(destination: SecondView()) {
                  Text("To Second View")
                  }
              }
          }
      }
    
    
      struct SecondView: View {
      var body: some View {
          Text("Button Text")
              .toolbar {
              ToolbarItem(placement: .principal) {
                  SearchBar2(text: .constant("Test"))
              }
          }
      }
    }
    

我希望这能为您的学习增加一些价值,继续努力,享受编码。

热点提示

OPT+单击 method/modifier 或基本上任何内容都会向您描述其功能。它对于找出问题非常有用,例如期望看到什么样的视图。甚至还有一个方便的 link,上面写着“打开开发人员文档”,它将提供更多数据。