SwiftUI中的实用性导航入门
SwiftUI是一个新的UI库,用于在Swift中构建用户界面。这个声明式框架允许开发者以声明的方式构建你的用户界面。
SwiftUI是数据驱动的,而UIKIt框架则是命令式的。
在这篇文章中,我们将看看SwiftUI中导航流和视图构造的不同方法。
我们还将看看MVC模式,它将使我们能够从视图中抽象出导航逻辑。
前提条件
要跟上这篇文章,你需要。
-
有关[SwiftUI]的知识。
-
在你的电脑上安装[苹果开发者工具]。
-
在你的电脑上安装[Xcode]和[Swift]。
MVC模式
模型-视图-控制器MVC是一种设计模式,它允许我们将应用程序模块化,并从视图中抽象出业务逻辑。
我们将在我们的应用程序中实现MVC模式,将导航逻辑从视图中抽象出来,实现实用的SwiftUI导航。
应用程序设置
在Xcode中,创建一个名为SwiftUI_Navigation 的新应用程序。确保你已经选择了SwiftUI 作为项目类型。
在项目目录中,创建一个名为Views 的新组,并在views 组中创建一个名为HomeView.swift 的新 SwiftUI 视图文件。
用以下代码更新HomeView.swift 文件。
struct HomeView: View {
@State private var activeIndex = 0
var body: some View {
TabView(selection: $activeIndex) {
Button("Tab B") {
activeIndex = 1
}
.tag(0)
.tabItem {
Label("A", systemImage: "a.circle")
}
Button("Tab A") {
activeIndex = 0
}
.tag(1)
.tabItem {
Label("B", systemImage: "b.circle")
}
}
}
}
@State 是一个SwiftUI属性,允许你在视图中存储一个值。默认情况下,不可能在SwiftUI视图中持有一个值会改变的变量。
为了克服这个问题,我们使用@State 属性包装器。
上述代码创建了一个TabView ,允许你在两个标签之间切换。然而,这种导航会导致SwiftUI视图中出现大量的模板代码。
当导航目的地的数量增加时,这就很明显了。比方说,有十个屏幕需要导航。
为了解决这个问题,我们可以将路由抽象为一个控制器,来处理导航。
控制器
在项目目录中,创建一个名为Controllers 的新组和一个名为Navigation.swift 的新Swift文件,并添加以下代码片段。
enum Tab {
case Tab_a
case Tab_b
case Tab_c
}
class HomeController: ObservableObject {
@Published var active = Tab.Tab_a
func navigate(tab: Tab) {
active = tab //sets the current active tab from the View file
}
}
在上面的代码片断中。
-
枚举
Tab将存储所有导航目的地的名称。将目的地存储为枚举,可以保持标签的当前状态并从任何屏幕上进行导航。 -
HomeController类扩展了ObservableObject,因为我们必须跟踪 SwiftUI 视图上的当前活动标签。 -
@Published注释将变量 设置为可观察,使得我们的 SwiftUI 视图可以观察到变化并导航到选择屏幕。active
模型
在项目目录中,创建一个名为Models 的新组,并创建一个名为News.swift 的新 Swift 文件,然后添加以下代码。
struct News: Identifiable {
let id = UUID() //Autogenerated Value
let title: String
let description:String
}
在上面的代码中,我们有容纳新闻项目的新闻模型。News 类扩展了Identifiable ,使其有一个唯一的id ,我们可以用它来识别一个新闻项目。
查看
在Views 组中创建一个名为NewsView.swift 的新 Swift 文件,并添加以下代码片断。
struct NewsView: View {
var news: News //Single news item
var body: some View {
VStack {
Text(news.title)
.font(.headline)
Text(news.description)
.font(.body)
}
}
}
在上面的代码片断中,我们创建了一个视图,它将在主屏幕上容纳一个新闻项目。
我们需要在Views 组中创建一个名为TabAView.Swift 的 SwiftUI 文件,并添加下面的代码。
struct TabAView: View {
@EnvironmentObject private var controller: HomeController
//We create a dummy list of news items. In a real application, this would come from an API
let news = [
News(title: "News A", description: "DescriptionA"),
News(title: "News A", description: "DescriptionA"),
News(title: "News A", description: "DescriptionA"),
News(title: "News A", description: "DescriptionA")
]
var body: some View {
NavigationView {
VStack {
Text("Home")
.font(.body)
Spacer()
Button("Search Items") {
controller.navigate(tab: .Tab_b)//navigating to the next view
}
//List of news Items
List(news) { newsItems in
NewsView(news: newsItems)
}
}
}
}
}
@EnvironmentObject注释是一个Swift包装器,用于应用程序中几个视图所访问的变量。每当 中的可观察变量发生变化时,视图文件应该能够更新 的变量值。HomeController@EnvironmentObject
我们还可以通过SwiftUI提供的NavigationLink ,并通过点击按钮来导航到下一个视图。
接下来,在Views 组中创建一个名为TabBView.swift 的新 SwiftUI 文件并添加以下代码。
struct TabBView: View {
@EnvironmentObject private var controller: HomeController
@State private var search = ""
var body: some View {
NavigationView {
Text("Searching \(search)")
.searchable(text: $search)
.navigationTitle("Search")
}
}
}
-
在上面的代码中,我们创建了一个带有搜索字段的SwiftUI视图,可以用来搜索新闻条目。
-
@State注释是一个Swift包装器,可以保持值发生变化的变量的当前状态。例如,每当我们向搜索文本字段输入一个字符时,我们就将当前的搜索文本存储在搜索变量中。
最后,我们需要用下面的代码片断更新HomeView.swift 。
struct HomeView: View {
@StateObject private var homeController = HomeController()
var body: some View {
TabView(selection: $homeController.active) {
TabAView()
.tag(Tab.Tab_a)
.tabItem {
Label("Tab A", systemImage: "house")
}
TabBView()
.tag(Tab.Tab_b)
.tabItem {
Label("Tab B", systemImage: "magnifyingglass")
}
TabCView()
.tag(Tab.Tab_c)
.tabItem {
Label("Tab C", systemImage: "gearshape")
}
}
.environmentObject(homeController)
}
}
在上面的代码中,我们正在设置应用程序的标签,使我们能够使用SwiftUI标签从一个标签导航到另一个。
总结
在这篇文章中,你已经了解了SwiftUI中导航流和视图构造的不同技术。
我们还讨论了MVC模式,它允许我们将导航逻辑从视图中抽象出来。
此外,MVC模式使应用程序更容易模块化,从而使其更容易维护。
现在你可以完成应用程序的搜索功能并实现详细页面。