SwifUI 学习(二)

217 阅读3分钟

「这是我参与2022首次更文挑战的第2天,活动详情查看:2022首次更文挑战

List

List类似UIKit中的UITableView。下面代码展示了现实三个静态的列表:

List {
    Text("List item one")
    Text("List item Two")
    Text("List item Three")
}

SwiftUI 中,这个导航控件是一个 NavigationView,它结合了 UINavigationBar 的显示样式和 UINavigationController 的视图控制器堆栈行为。 要引入一个,只需在列表周围添加 NavigationView

NavigationView {
    List {
        Text("List item one")
        Text("List item Two")
        Text("List item Three")
    }
}

当预览视图更新时,您会在列表上方看到一个很大的空间,这是导航栏所在的位置。 然而,它是空的,因为我们没有给它一个标题。 navigationTitle() 修饰符接受某种文本并显示在导航栏中。 所以,我们会这样写:

NavigationView {
    List {
        Text("List item one")
        Text("List item Two")
        Text("List item Three")
    }
    .navigationTitle("Menu")
}

是的,修饰符附加到列表而不是导航视图 - 想想我们如何设置 UIViewController 的标题而不是尝试设置 UINavigationController 的标题。

image.png

当你有固定的表格单元格时,静态文本可以正常工作,但在我们的例子中,我们有很多菜单项要加载到多个部分——早餐、主菜、甜点和饮料。 我们真正想做的是从 JSON 加载我们的菜单数据,然后将其用于我们的列表项,这实际上并不难完成。

首先我们需要加载我们的数据。 您已经导入的 Helper.swift 文件包含用于从应用程序包加载 Codable JSON 的代码,这非常适合加载我们的 menu.json 文件。 因此,现在将此属性添加到 ContentView 结构中:

先从json文件中还在数据

let menu = Bundle.main.decode([MenuSection].self, from: "menu.json")

然后,可以使用ForEach来遍历List

List {
    ForEach(menu) { _ in
        Text("Hello World")
    }
}

这几乎可行,但我们需要做的最后一件事。 SwiftUI 需要知道如何识别表格中的每个单元格——它需要准确地知道哪个是哪个单元格,这样它就可以在我们询问时为我们添加和删除内容。 当我们有一个静态列表时,这不是问题,因为它可以看到有三个,但现在我们有一个动态列表,我们需要告诉它每个部分的独特之处。

我们可以通过使这两种类型符合 Identifiable 来告诉 SwiftUI 使用这些标识符。 这个协议只有一个要求,那就是符合的类型必须有一个名为 id 的属性,可以唯一地标识它们。 我们已经有了,所以只需将 Identifiable 添加到这两种类型就足够了:

struct MenuSection: Codable, Identifiable {

struct MenuItem: Codable, Equatable, Identifiable {

我们可以在列表访问每个section中的items

List {
    ForEach(menu) { section in
        Text(section.name)
        ForEach(section.items) { item in
            Text(item.name)
        }
    }
}

虽然这可行,但并不理想——它不会在我们的表格中创建任何视觉结构,所以我们将把它分解。 执行此操作的标准 UIKit 方式是使用表格视图部分,而 SwiftUI 正是为此提供了部分视图。 我们可以将 Text(section.name) 替换为 Section,并将其用作其标题,即该部分开头的文本。 内部的 ForEach - 包含我们的菜单项的那个 - 然后位于该部分内,因此 SwiftUI 将了解我们如何将事物组合在一起。

List {
    ForEach(menu) { section in
        Section(header: Text(section.name)) {
            ForEach(section.items) { item in
                Text(item.name)
            }
        }
    }
}

默认情况下,SwiftUI 为我们列出了 UITableView 的“普通”样式,但我们可以通过在 navigationTitle() 之后添加另一个修饰符来改变它:

.listStyle(.grouped)

完整的代码如下:

List {
    ForEach(menu) { section in
        Section(header: Text(section.name)) {
            ForEach(section.items) { item in
                Text(item.name)
            }
        }
    }
}
.navigationTitle("Menu")
.listStyle(GroupedListStyle())