Cách hiển thị dữ liệu phân cấp với SwiftUI 4
Ai trong số các bạn chưa từng đối mặt với vấn đề hiển thị cấu trúc phân cấp trong một ứng dụng?
SwiftUI cung cấp khả năng này chỉ với một vài dòng mã, sử dụng chế độ xem Danh sách và Nhóm phác thảo . Trong bài viết này, tôi sẽ chỉ cho bạn cách thực hiện việc này trong một vài bước.
Giả sử chúng ta cần hiển thị thông tin phân cấp trong chế độ xem Danh sách, cho phép người dùng ẩn và hiển thị các phần khác nhau của phân cấp.
Chẳng hạn, chúng tôi muốn điều hướng phần sau của hệ thống tệp, bao gồm các thư mục và tệp. Đây là một cây phân cấp điển hình.
Sau đó bắt đầu và khởi chạy Xcode để tạo dự án Ứng dụng mới có tên HierarchicalDemo:
Bước đầu tiên là tạo ra một cấu trúc mô hình hóa một nút của cây phân cấp. Trong trình kiểm tra dự án, trong nhóm Mô hình , chúng tôi tạo một tệp nhanh có tên NodeInfo.swift và xác định cấu trúc NodeInfo :
Mỗi nút có một tên, một hình ảnh và một màu sắc đại diện cho nó tùy thuộc vào việc nó là một thư mục hay một tập tin, nó có thể có các nút con. Cấu trúc tuân theo giao thức Có thể nhận dạng , để mỗi phiên bản có thể được xác định duy nhất trong dạng xem Danh sách.
struct NodeInfo: Identifiable{
var id = UUID()
var name: String
var image: String
var color: Color
var children: [NodeInfo]?
}
struct NodeCell: View {
var nodeItem: NodeInfo
var body: some View {
HStack{
Image(systemName: nodeItem.image)
.resizable()
.scaledToFit()
.frame(width: 25,height: 25)
.foregroundColor(nodeItem.color)
Text(nodeItem.name)
}
}
}
Bây giờ chúng ta có một mô hình cho một nút của cấu trúc phân cấp và một dạng xem cho một hàng trong dạng xem Danh sách. Bước tiếp theo là xác định trong cấu trúc ContentView mảng không đổi NodeItems triển khai cây hệ thống tệp ở trên:
let nodeItems: [NodeInfo] =
[NodeInfo(name: "ROOT", image: "folder",color: .orange, children:
[NodeInfo(name:"Documents", image: "folder.circle",color: .blue, children:[NodeInfo(name: "Accounting", image: "folder.circle",color: .blue, children: [NodeInfo(name: "rental.doc", image: "doc.circle",color: .cyan),NodeInfo(name: "invoice1.doc", image: "doc.circle", color: .cyan),NodeInfo(name: "invoice2.doc", image: "doc.circle",color: .cyan)])]),
NodeInfo(name: "Photo", image: "folder.circle",color: .blue, children: [NodeInfo(name: "Selfie", image: "folder.circle",color:.blue,children: [NodeInfo(name: "john.png", image: "photo.circle",color: .green),NodeInfo(name: "Julie.png", image: "photo.circle",color: .green)]),NodeInfo(name: "mybirthday.png", image: "photo.circle",color: .green)]),
NodeInfo(name: "Video", image: "folder.circle",color:.blue, children: [NodeInfo(name: "Holiday", image: "folder.circle",color:.blue,children: [NodeInfo(name: "mountins.wav", image: "video.circle",color: .orange),NodeInfo(name: "sea.wav", image: "video.circle",color:.orange)]),NodeInfo(name: "birthday.mp3", image: "video.circle.fill",color:.orange),NodeInfo(name: "cat.wav", image: "video.circle",color:.orange)]),
NodeInfo(name: "booking.pdf", image: "doc.circle",color: .green)])]
Vì chúng tôi muốn danh sách có tiêu đề tùy chỉnh, trong ContentView.swift , chúng tôi xác định cấu trúc SectionHeader :
struct SectionHeader: View{
var nodeItem: NodeInfo
var body: some View{
HStack{
Image(systemName: nodeItem.image)
.resizable()
.scaledToFit()
.frame(width: 25, height: 25)
Text(nodeItem.name)
.font(.title2.bold())
}
.foregroundColor(nodeItem.color)
}
}
Bây giờ là lúc để xây dựng danh sách phân cấp của chúng tôi. Trong nội dung contentView, chúng tôi nhập mã bên dưới:
var body: some View {
List{
ForEach(nodeItems) { item in
Section(header: SectionHeader(nodeItem: item)){
OutlineGroup(item.children ?? [NodeInfo](), children: \.children){child in
NodeCell(nodeItem: child)
}
}
}
}
.listStyle(InsetListStyle())
}
Và đây là kết quả cuối cùng:

![Dù sao thì một danh sách được liên kết là gì? [Phần 1]](https://post.nghiatu.com/assets/images/m/max/724/1*Xokk6XOjWyIGCBujkJsCzQ.jpeg)



































