首页 > 解决方案 > 按最新和最旧对数据进行排序

问题描述

我想按最后一次点击(最新)对我的自定义数组进行排序。我可以按名称或 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())
    }
}

标签: swiftui

解决方案


关注根据问题进行的排序,以下内容对我来说效果很好。唯一显着的变化是按最旧的排序。这是我的测试代码:

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模型中。

我还将名称不好的重命名DataArrayCityData.

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
}

推荐阅读