一同养成写作习气!这是我参与「日新计划 4 月更文挑战」的第16天,点击检查活动概况。

今日职言:商业环境的改动是敏捷且规律莫测的,你要做的是,一旦决定了就当即去做。

在本章中,咱们将根据List列表的基本运用办法上,进阶学习List列表的更多用法。

本章节将分成3个部分讲解。

1、onDelete滑动删去和onMove拖动排序

2、ContextMenu上下文菜单

3、ActionSheets弹窗的运用

那咱们开端吧。

榜首部分:onDelete滑动删去和onMove拖动排序

首先,咱们先创立一个新项目,命名为SwiftUIList02

SwiftUI极简教程16:List列表的使用方法进阶学习

咱们创立一个简略的列表,这儿引证之前的List创立的代码。

完好代码如下:

import SwiftUI
struct Message: Identifiable {
var id = UUID()
var name: String
var image: String
}
// 界说数组,寄存数据
var Messages = [Message(name: "这是微信", image: "weixin"),Message(name: "这是QQ", image: "qq"),Message(name: "这是微博", image: "weibo"),Message(name: "这是手机", image: "phone"),Message(name: "这是邮箱", image: "mail"),]
struct ContentView: View {
var body: some View {
// 列表
List {
ForEach(Messages) { Message in
HStack {
Image(Message.image)
.resizable()
.frame(width: 40, height: 40)
.cornerRadius(5)
Text(Message.name)
.padding()
}
}
}
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}

这儿咱们运用了List列表和ForEach循环的办法建立了一个列表。

运转后的作用如下:

SwiftUI极简教程16:List列表的使用方法进阶学习

完成单条List列表数据的滑动删去,咱们需求调用.onDelete(perform:XXXX)修饰符,它是ForEach的修饰符,用来删去List中的一条条数据;

perform中引证的是删去的办法,咱们界说一个删去办法为deleteRow,详细完成办法如下:

//滑动删去办法
func deleteRow(at offsets: IndexSet) {
 Messages.remove(atOffsets: offsets)
}

deleteRow删去列的办法中,咱们接纳单一的IndexSet类型的参数,它是用来定位要删去的列的方位的。

然后调用remove(atOffsets:XXXX)办法来删去Messages数组中的被定位的特定项。

这样咱们就可以完成列表的滑动删去,运转模拟器,点击一行向右滑动,咱们就可以完成删去一行数据。

SwiftUI极简教程16:List列表的使用方法进阶学习

科普一个知识点。

咱们运转的时分会发现,咱们滑动删了1行,体系主动又“创立”了一行回来。

这是因为每次咱们删去List中特定的数据项时,体系会主动更新UI,而更新的数据源是咱们创立的Messages数组。

也就是说,每次删去后,体系从头“渲染”页面,但Messages数组数据没有改动,也就删去了啥,就恢复了啥,就变成了怎样也删去不了了。

咱们期望的是,删去了特定的数据项时,Messages数组的值也需求同步被更改。

因此,咱们有必要让SwiftUI监控特点,并在特点值发生改动时更新UI。咱们运用@State界说数据:

@State var messagesItems = Messages

并且将ForEach循环的数据源由Messages数组,变为咱们用@State界说的messagesItems,一起在deleteRow办法中,操作remove的目标也换成messagesItems数组。

这样,咱们每次删去数组特定项的时分,messagesItems数组就知道咱们删去了什么数据,并且“记住”它,在UI改写的时分,ForEach就根据messagesItems数组内的内容遍历数据。

SwiftUI极简教程16:List列表的使用方法进阶学习

好了,咱们完成了List页面的滑动删去操作了。

再弥补一个知识点。

如果咱们给List列表创立导航栏,还可以运用SwiftUI现已封装好的EditButton修改按钮,然后完成列表快速进入修改状况,这在Apple自家的备忘录中可以看到。

当咱们点击Edit按钮时,按钮文字会变成done,一起List列表都变成可删去的形式。

NavigationView {
// 列表
List {
ForEach(messagesItems) { Message in
HStack {
Image(Message.image)
.resizable()
.frame(width: 40, height: 40)
.cornerRadius(5)
Text(Message.name)
.padding()
}
}.onDelete(perform: deleteRow)
}.navigationBarItems(trailing: EditButton())
}

SwiftUI极简教程16:List列表的使用方法进阶学习

再延伸地弥补一个知识点。

List列表修改形式下,除了删去之前,还可以针对于数据项进行拖动排序,咱们用的是.onMove(perform:XXXX)修饰符,它也是ForEach的修饰符,用来完成List列表的拖动单条数据的改动它的排序顺序;

NavigationView {
// 列表
List {
ForEach(messagesItems) { Message in
HStack {
Image(Message.image)
.resizable()
.frame(width: 40, height: 40)
.cornerRadius(5)
Text(Message.name)
.padding()
}
}
  .onDelete(perform: deleteRow)
  .onMove(perform: moveItem)
}.navigationBarItems(trailing: EditButton())
}

perform中引证的是排序的办法,咱们界说一个删去办法为moveItem,详细完成办法如下:

// 拖动排序办法
func moveItem(from source: IndexSet, to destination: Int) {
 messagesItems.move(fromOffsets: source, toOffset: destination)
}

同样,咱们接纳单一的IndexSet类型的参数,它是用来定位要排序的列的方位。

然后它的排序数值为Int类型,简略来说,初始的排序是0、1、2、3、4,假设咱们把3拖动到0,那么体系将主动更新从头排列顺序。

然后完成排序的作用。

SwiftUI极简教程16:List列表的使用方法进阶学习

快来试试吧!

第二部分:ContextMenu上下文菜单

ContentMenu上下文菜单是iOS13引证的一个新功能,作用为长按列表时,弹出一个悬浮窗口,用于方便操作。

iPhone傍边存在很多这样的交互,示例:长按体系设置,翻开方便操作弹窗。

SwiftUI极简教程16:List列表的使用方法进阶学习

完成ContentMenu上下文菜单的办法也很简略,运用.contentMenu修饰符,在修饰符里边构建需求展示或者操作的内容。

这儿咱们测验做一个长按删去的操作,长按列表的一个项目,弹出上下文ContentMenu菜单,里边是一个删去按钮,点击按钮,删去指定行的数据。

.contextMenu {
 Button(action: {
  // 点击删去
 }) {
  HStack {
   Text("删去")
   Image(systemName: "trash")
  }
 }
}

SwiftUI极简教程16:List列表的使用方法进阶学习

然后,咱们完成下删去的操作,会有些复杂,请耐心查阅。

它不像咱们运用ForEach运用的.onDelete删去修饰符的办法不相同,ContentMenu上下文菜单没有索引定位到特定的数据项,也就不知道咱们点击选中的是哪一条数据。

这就需求咱们自己定位到Messages数组里边的Messageid,这样咱们就可以经过id定位到是数组中的哪一条数据了。

办法如下:

//删去的办法
func delete(item Message: Message) {
 if let index = self.messagesItems.firstIndex(where: { $0.id == Message.id }) {
  self.messagesItems.remove(at: index)
 }
}

咱们界说了一个delete的函数办法,接纳了一个Message目标,并在Messages数组中搜索Message目标的索引。

为了找到Message目标的索引,咱们调用firstIndex函数循环遍历数组,并将给定Messagesid与数组中的id进行比较。

如果有id相同,则firstIndex函数回来Messages数组的索引。

这样咱们就知道长按的是哪一条数据了!

接下来,咱们就可以经过调用remove(at:XXXX)修饰符从Messages数组中删去对应的数据项。

self.delete(item: Message)

SwiftUI极简教程16:List列表的使用方法进阶学习

咱们运转一下模拟器,长按,体系会给出ContentMenu上下文菜单,它是一个删去按钮,咱们点击删去按钮,该行数据就被删去了。

完好代码如下:

import SwiftUI
struct Message: Identifiable {
var id = UUID()
var name: String
var image: String
}
// 界说数组,寄存数据
var Messages = [Message(name: "这是微信", image: "weixin"),Message(name: "这是QQ", image: "qq"),Message(name: "这是微博", image: "weibo"),Message(name: "这是手机", image: "phone"),Message(name: "这是邮箱", image: "mail"),]
struct ContentView: View {
 // 界说数组
@State var messagesItems = Messages
var body: some View {
NavigationView {
// 列表
List {
ForEach(messagesItems) { Message in
HStack {
Image(Message.image)
.resizable()
.frame(width: 40, height: 40)
.cornerRadius(5)
Text(Message.name)
.padding()
}
.contextMenu {
Button(action: {
// 点击删去
self.delete(item: Message)
}) {
HStack {
Text("删去")
Image(systemName: "trash")
}
}
}
}
.onDelete(perform: deleteRow)
.onMove(perform: moveItem)
}.navigationBarItems(trailing: EditButton())
}
}
//删去的办法
func delete(item Message: Message) {
if let index = self.messagesItems.firstIndex(where: { $0.id == Message.id }) {
self.messagesItems.remove(at: index)
}
}
// 滑动删去办法
func deleteRow(at offsets: IndexSet) {
messagesItems.remove(atOffsets: offsets)
}
// 拖动排序办法
func moveItem(from source: IndexSet, to destination: Int) {
messagesItems.move(fromOffsets: source, toOffset: destination)
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}

SwiftUI极简教程16:List列表的使用方法进阶学习

第三部分:ActionSheets弹窗的运用

弹窗傍边,咱们在之前的章节学习了ModelView弹窗,这儿咱们再拓宽一种弹窗形式,叫做.actionSheet

它算是.sheet的另一种形式,常用在用户敏感操作的二次承认,但又不像Alerts正告弹窗那么严肃,属于一般强调。

SwiftUI极简教程16:List列表的使用方法进阶学习

.actionSheetAlerts正告弹窗的完成方式大体相同。

.actionSheet(isPresented:$showActionSheet) {
//ActionSheet结构体
}

咱们还是运用isPresented触发,咱们界说一个变量showActionSheet的状况,初始状况是false

@State varshowActionSheet = false

接下来,咱们完成下ActionSheet结构体:

// ActionSheet弹窗
.actionSheet(isPresented: self.$showActionSheet) {
 ActionSheet(
  title: Text("你确定要删去此项吗?"),
  message: nil,
  buttons: [
   .destructive(Text("删去"), action: {
    //点击删去
    }),
   .cancel(Text("撤销")
    ])
 }

SwiftUI极简教程16:List列表的使用方法进阶学习

下面,咱们做一个“风趣”的操作。

咱们承接上一部分的内容,长按列表,弹出一个ContentMenu上下文菜单,里边是一个删去按钮,点击删去按钮,翻开ActionSheet弹窗,里边又是一个删去按钮,点击ActionSheet弹窗内的删去按钮,删去列表的数据项。

SwiftUI极简教程16:List列表的使用方法进阶学习

咱们就完成了根据ActionSheet弹窗的删去操作啦!

完好代码如下:

import SwiftUI
struct Message: Identifiable {
var id = UUID()
var name: String
var image: String
}
// 界说数组,寄存数据
var Messages = [
Message(name: "这是微信", image: "weixin"),
Message(name: "这是QQ", image: "qq"),
Message(name: "这是微博", image: "weibo"),
Message(name: "这是手机", image: "phone"),
Message(name: "这是邮箱", image: "mail"),
]
struct ContentView: View {
// 界说数组
@State var messagesItems = Messages
@State var showActionSheet = false
var body: some View {
NavigationView {
   // 列表
List {
ForEach(messagesItems) { Message in
HStack {
Image(Message.image)
.resizable()
.frame(width: 40, height: 40)
.cornerRadius(5)
Text(Message.name)
.padding()
}
// 上下文菜单
.contextMenu {
Button(action: {
// 点击翻开ActionSheet弹窗
self.showActionSheet.toggle()
}) {
HStack {
Text("删去")
Image(systemName: "trash")
}
}
}
// ActionSheet弹窗
.actionSheet(isPresented: self.$showActionSheet) {
ActionSheet(
title: Text("你确定要删去此项吗?"),
message: nil,
buttons: [
.destructive(Text("删去"), action: {
//点击删去
self.delete(item: Message)
}),
.cancel(Text("撤销"))
])
}
}
.onDelete(perform: deleteRow)
.onMove(perform: moveItem)
}.navigationBarItems(trailing: EditButton())
}
}
// 删去的办法
func delete(item Message: Message) {
if let index = messagesItems.firstIndex(where: { $0.id == Message.id }) {
messagesItems.remove(at: index)
}
}
// 滑动删去办法
func deleteRow(at offsets: IndexSet) {
messagesItems.remove(atOffsets: offsets)
}
// 拖动排序办法
func moveItem(from source: IndexSet, to destination: Int) {
messagesItems.move(fromOffsets: source, toOffset: destination)
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}

快来动手试试吧!

如果本专栏对你有协助,无妨点赞、评论、重视~