swiftui - 按最新和最旧对数据进行排序
问题描述
我想按最后一次点击(最新)对我的自定义数组进行排序。我可以按名称或 ID 排序,但我无法按时间排序。我在网上找不到类似的问题,这让我很头疼。正如您在下面的代码中看到的那样,我想按最后一次点击对收藏夹列表进行排序。在此先感谢您的帮助。
import Foundation
import SwiftUI
struct DataArray: Identifiable {
let id: Int
let cities: String
let name1: String
let name2: String
let isFavorite: Bool
var date = Date()
}
public struct ListDataArray {
static let dot = [
DataArray(id: 1,
cities: "Baltimore"
name1: "John",
name2: "Mike",
isFavorite: False),
DataArray(id: 2,
cities: "Frederick"),
name1: "Joe",
name2: "Swift",
isFavorite: False),
DataArray(id: 3,
cities: "Catonsville"
name1: "Susan",
name2: "Oliver",
isFavorite: False),
// There will be a lot of data
]
}
class Prospect: ObservableObject {
@Published var datas: [DataArray] = []
init() {
fetchDataArrays()
}
private func fetchDataArrays() {
let items = ListDataArray.dot
datas = items
}
// To View Favorite
@Published var showFavorite: Bool = false
}
struct Home: View {
@EnvironmentObject var items: Prospect
var body: some View {
ScrollView {
LazyVStack {
ForEach(items.datas) { data in
VStack {
ButtonView(data: data)
.environmentObject(items)
Text("\(data.id)")
.font(.title3)
Text(data.cities)
.font(.subheadline)
Text(data.name1)
.font(.subheadline)
Text(data.name2)
.font(.subheadline)
}
padding()
}
.padding()
}
}
}
}
struct ButtonView: View {
@EnvironmentObject var items: Prospect
let data: DataArray
var index: Int {
items.datas.firstIndex(where: { $0.id == data.id }) ?? 0
}
var body: some View {
HStack {
Button(action: {
self.items.datas[self.index].isFavorite.toggle()
} label: {
Image(systemName: self.items.datas[self.index].isFavorite ? "suit.heart.fill" : "suit.heart").padding()
})
Spacer()
Button(action: {
items.showFavorite.toggle()
} label: {
Image(systemName: "person").padding()
})
.sheet(isPresented: $items.showFavorite) {
FavoriteView()
.environmentObject(items)
}
}
}
}
struct FavoriteView: View {
@EnvironmentObject var items: Prospect
@State var selection = 0
let sortingNames = ["Newest", "Oldest", "A to Z", "Z to A"]
var body: some View {
VStack {
HStack {
ForEach(0...<4) { num in
Button(action: {
selection = num
}, label: {
Spacer()
Text(sortingNames[num])
.forgroundColor(selection == num ? Color.blue: Color.black)
Spacer()
})
}
}
List {
ForEach(sorting()) { data in
if data.isFavorite {
VStack(spacing: 10) {
Text(data.cities)
Text(data.name1)
Text(data.name2)
}
.font(.body)
}
}
.padding()
}
Spacer()
}
}
private func sorting() -> [DataArray] {
switch selection {
case 0:
// Here I want to sort by the Newest...
return items.datas.sorted(by: { $0.date < $1.date })
case 1:
// Here I want to sort by the Oldest...
return items.datas.sorted(by: { $0.date < $1.date })
case 2:
return items.datas.sorted(by: { $0.cities < $1.cities })
case 3:
return items.datas.sorted(by: { $0.cities > $1.cities })
}
}
}
struct Home_Previews: PreviewProvider {
static var previews: some View {
Home()
.environmentObject(Prospect())
}
}
解决方案
仅关注根据问题进行的排序,以下内容对我来说效果很好。唯一显着的变化是按最旧的排序。这是我的测试代码:
import SwiftUI
@main
struct TestApp: App {
var body: some Scene {
WindowGroup {
ContentView()
}
}
}
struct DataArray: Identifiable {
let id: Int
let cities: String
let name1: String
let name2: String
let isFavorite: Bool
var date = Date()
}
struct ContentView: View {
let dataArr = [DataArray(id: 1,cities: "Baltimore", name1: "John", name2: "Mike", isFavorite: true,
date: Date()),
DataArray(id: 2,cities: "Frederick" ,name1: "Joe", name2: "Swift", isFavorite: true,
date: .now+1),
DataArray(id: 3,cities: "Catonsville", name1: "Susan", name2: "Oliver", isFavorite: true,
date: .now+2)
]
@State var selection = 0
let sortingNames = ["Newest", "Oldest", "A to Z", "Z to A"]
var body: some View {
VStack {
HStack {
ForEach(0..<4) { num in
Button(action: { selection = num}) {
Text(sortingNames[num])
.foregroundColor(selection == num ? Color.blue: Color.black)
}
}
}
List {
ForEach(sorting()) { data in
if data.isFavorite {
VStack(spacing: 10) {
Text("\(data.id)").foregroundColor(.red) // <-- for testing
Text(data.cities)
Text(data.name1)
Text(data.name2)
}
}
}
}
}
}
func sorting() -> [DataArray] {
switch selection {
case 0:
// Here I want to sort by the Newest...
return dataArr.sorted(by: { $0.date < $1.date })
case 1:
// Here I want to sort by the Oldest...
return dataArr.sorted(by: { $0.date > $1.date }) // <--- here
case 2:
return dataArr.sorted(by: { $0.cities < $1.cities })
case 3:
return dataArr.sorted(by: { $0.cities > $1.cities })
default:
return dataArr // <--- here need a default
}
}
}
编辑1:
由于我不知道您真正想对您的应用程序做什么,因此我只是修改了您的(测试)代码,以向您展示一种对数据进行排序的方法。
这里的主要重点是拥有一个数据的真实来源,从ContenView
@StateObject var items = Prospect()
. 还sorting()
对数据进行了排序in-place
,使其看起来到处都是排序的。移动sorting()
到您的Prospect
模型中。
我还将名称不好的重命名DataArray
为CityData
.
struct ContentView: View {
@StateObject var items = Prospect()
var body: some View {
Home().environmentObject(items)
}
}
struct Home: View {
@EnvironmentObject var items: Prospect
var body: some View {
ScrollView {
LazyVStack {
ForEach(items.datas) { data in
VStack {
ButtonView(data: data)
Text("\(data.id)").font(.title3)
Text(data.cities).font(.subheadline)
Text(data.name1).font(.subheadline)
Text(data.name2).font(.subheadline)
}.padding()
}.padding()
}
}
}
}
struct ButtonView: View {
@EnvironmentObject var items: Prospect
@State var data: CityData // <--- here
@State var index: Int = 0 // <--- here
var body: some View {
HStack {
Button(action: { items.datas[index].isFavorite.toggle() }) {
Image(systemName: items.datas[index].isFavorite ? "suit.heart.fill" : "suit.heart").padding()
}
Spacer()
Button(action: { items.showFavorite.toggle() }) {
Image(systemName: "person").padding()
}
}
.onAppear {
if let ndx = items.datas.firstIndex(where: { $0.id == data.id }) {
index = ndx
}
}
.sheet(isPresented: $items.showFavorite) {
FavoriteView().environmentObject(items)
}
}
}
struct FavoriteView: View {
@Environment(\.dismiss) var dismiss
@EnvironmentObject var items: Prospect
@State var selection = 0
let sortingNames = ["Newest", "Oldest", "A to Z", "Z to A"]
var body: some View {
VStack {
Button(action: {dismiss()}) {
Text("Done").foregroundColor(.blue) // <-- for testing on macos
}
HStack {
ForEach(0..<4) { num in
Button(action: {
selection = num
items.sorting(selection) // <--- here
}) {
Text(sortingNames[num])
.foregroundColor(selection == num ? Color.blue: Color.black)
}
}
}
List {
ForEach(items.datas) { data in // <--- here
if data.isFavorite {
VStack(spacing: 10) {
Text("\(data.id)").foregroundColor(.red) // <-- for testing
Text(data.cities)
Text(data.name1)
Text(data.name2)
}
}
}
}
}
}
}
class Prospect: ObservableObject {
@Published var datas: [CityData] = []
@Published var showFavorite: Bool = false
init() {
fetchCityDatas()
}
private func fetchCityDatas() {
datas = ListCityData.dot
}
// --- sort in place note sort() not sorted() ---
func sorting(_ selection: Int) {
switch selection {
case 0:
// Here I want to sort by the Newest...
datas.sort(by: { $0.date < $1.date })
case 1:
// Here I want to sort by the Oldest...
datas.sort(by: { $0.date > $1.date }) // <--- here
case 2:
datas.sort(by: { $0.cities < $1.cities })
case 3:
datas.sort(by: { $0.cities > $1.cities })
default:
break
}
}
}
public struct ListCityData {
static let dot = [CityData(id: 1,cities: "Baltimore", name1: "John", name2: "Mike", isFavorite: true,
date: .now),
CityData(id: 2,cities: "Frederick" ,name1: "Joe", name2: "Swift", isFavorite: true,
date: .now+10),
CityData(id: 3,cities: "Catonsville", name1: "Susan", name2: "Oliver", isFavorite: true,
date: .now+20)
]
}
// --- here renamed and using var ---
struct CityData: Identifiable {
let id: Int
var cities: String
var name1: String
var name2: String
var isFavorite: Bool
var date: Date
}
推荐阅读
- swift - Get nil when looking for file in subdirectory of main bundle
- javascript - 禁用按钮单击,直到所有输入字段中都有文本(javascript & jquery)
- sql - PostgreSQL - 如何让简单的查询更快
- reactjs - 如何用 React JS 实现 Packery?
- html - 响应式视图,例如使用 Boostrap 4 和 Ember 的 Whatsapp web
- google-chrome - 在 webRequest.onBeforeRequest 上添加 redirectUrl 后,Chrome 扩展无法正确加载
- python - xlsxwriter 创建的损坏的 xlsx 文件
- rest - 仪表板 REST 端点的命名约定
- reactjs - 单击下拉菜单链接后如何在反应中更改语言下拉按钮图像?
- php - Laravel,从调用方法中获取返回值