listView在APP交互上是一个很高频的容器组件了,在传统的UIKit中一般是给tableview或者collectionView设置delegate,controller完成cell的制作和UI束缚,控制列表的翻滚交互和UI风格。在swiftUI中该如何控制list的这些特性,本文做一个简略的记载。

静态的listview

假如要展现的是一些固定数据的且数据量不大的list,简略几行代码就能完成

var body: some View {
    List{
        Text("Hello, World!")
        Text("Hello, World!")
        Text("Hello, World!")
    }
}

List默许的款式是InsetGroupedListStyle,作用如下

SwiftUI List、自定义cell、分组

分组的listview

SwiftUI里用Sectoin表明一个分组

Section {
        TextField("输入名字", text: $username)
        Toggle(isOn: $isPrivate) {
            Text("隐私")
        }
        Button{}label: {
            Text("退出")
        }
    } header: {
        Text("个人")
    }
    Section {
        Slider(value: $fontSize, in: 1...10)
        Picker("主题", selection: $appearance) {
            Text("Dark").tag(AppearanceStyle.dark)
            Text("Light").tag(AppearanceStyle.light)
            Text("Auto").tag(AppearanceStyle.auto)
        }
    } header: {
        Text("主题")
    }
    Section {
        HStack{
            Text("版本")
            Spacer()
            Text("1.0.0")
        }
    } header: {
        Text("关于")
    }
}

SwiftUI List、自定义cell、分组

动态的listview

listview的呈现大部分情况下都是依据服务的回来的数据动态体现的,这里mock一个数组模拟api的回来数据,显现一个生果的列表。

struct Food{
    var name: String
    var icon: String
    var isFavorite: Bool
    static func preview() -> [Food]{
        return [
            Food(name: "苹果", icon: "", isFavorite: true),
            Food(name: "草莓", icon: "", isFavorite: true),
            Food(name: "香蕉", icon: "", isFavorite: true),
            Food(name: "樱桃", icon: "", isFavorite: true),
            Food(name: "葡萄", icon: "", isFavorite: true),
            Food(name: "西瓜", icon: "", isFavorite: true),
        ]
    }
}

直接在List中显现一个arr会报错 「Initializer ‘init(_:rowContent:)’ requires that ‘Food’ conform to ‘Identifiable’」,意思就是你显现的Model不具有仅有性,此时能够供给一个名为id的特点,指定一个Model里的特点作为仅有标识就好了。

List{
    let fruits = Food.preview()
    List(fruits, id: \.name) { food in
        Text(food.name)
}

这里供给的id是fruit的name,mock的数据里是仅有的,但真实的项目里不会用这种性质的字段最为id,一般会给Model通过完成Identifiable的方式扩展一个UUID的id特点来处理。

struct Food: Identifiable{
    ......
   let id = UUID()
}

这个时候你的list中不供给id特点也不会报错了,页面能正常展现

SwiftUI List、自定义cell、分组

创立自定义cell

SwiftUI里不需要像在UIKit下去创立一个集成UITableViewCell的view,只要在List中指定要显现的UI组件即可,假如UI比较复杂,能够抽取出一个独立的view。

struct FoodRow: View{
    let food: Food
    var body: some View{
        HStack{
            Text(food.icon).font(.title)
            Text(food.name)
            Spacer()
            Image(systemName: food.isFavorite ? "heart.fill" : "heart")
        }
    }
}

设置group款式,以及group的header和footer

新增一个array,分组显现为生果和零食。你能够往List里随意的添加section来完成分组,section有自定义的header和footer特点来显现组的头尾信息,运用默许的InsetGroupedListStyle款式。或者你也能够用DisclosureGroup来显现一个可折叠的分组作用

SwiftUI List、自定义cell、分组

数据的添加和删除

先说删除,主页显现数据的array标示为@State,其次list有一个delete的方法,传入一个block回调

@inlinable public func onDelete(perform action: ((IndexSet) -> Void)?) -> some DynamicViewContent

SwiftUI List、自定义cell、分组

添加数据,直接在barItem添加点击事件,往数据里新增一条记载就好

toolbar {
    Button {
        fruits.append(Food(name: "未知food", icon: "⚠️", isFavorite: false))
    } label: {
        Text("新增")
    }
}

SwiftUI List、自定义cell、分组