如何在SwiftUI中开始使用务实的导航功能

120 阅读2分钟

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模式使应用程序更容易模块化,从而使其更容易维护。

现在你可以完成应用程序的搜索功能并实现详细页面。