首页 > 解决方案 > 按日期发布 tableview 数据的排序顺序 | 迅速

问题描述

本质上,我有一个使用 JSON 数据填充的 tableview,tableview 包含使用 JSON 对数据进行分组的部分allowdate

allowdate如下所示,它包含一个日期,但不是数字格式,而是看起来像:March 26th 2020所以很难控制它在 tableview 中显示的顺序。

fetchJSON我做的功能中:

self.structure.sort { $1. allowdate < $0.allowdate }

但这不能正常工作,并且无法将例如 1 月的日期放在 3 月的日期之上。

var sections = [TableSection]()
var structure = [TableStructure]()

private func fetchJSON() {

guard let url = URL(string: "\(URL.url)example"),
    let value = name.addingPercentEncoding(withAllowedCharacters: .urlQueryValueAllowed)
    else { return }

var request = URLRequest(url: url)
request.httpMethod = "POST"
request.httpBody = "item1=\(value)&item2=\(value)".data(using: .utf8)

URLSession.shared.dataTask(with: request) { data, _, error in
    guard let data = data else { return }



    do {
        let decoder = JSONDecoder()
        decoder.keyDecodingStrategy = .convertFromSnakeCase
        self.structure.sort { $1. allowdate < $0.allowdate }
        let res = try decoder.decode([TableStructure].self, from: data)
        let grouped = Dictionary(grouping: res, by: { $0. allowdate })
        let keys = grouped.keys.sorted()
        self.sections = keys.map({TableSection(date: $0, items: grouped[$0]!)})
        DispatchQueue.main.async {
            self.tableView.reloadData()
        }

    }

    catch {
        print(error)
    }
    }.resume()

}

JSON:

[
    {
        "person": "Jack",
        "allowdate": "March 26th 2020",
        "ready_time": "10:00 am"
    }
]

要解码此 JSON,我使用以下结构:

struct TableSections {
    let date : String
    var items : [TableStructure]
}


struct TableStructure: Decodable {

    let person: String
    let allowdate: String
    let ready_time: String

    enum CodingKeys : String, CodingKey {
        case person, allowdate, ready_time

  }

}

标签: iosjsonswift

解决方案


我在操场上试过这个。它似乎适用于不同的序数:

import UIKit

let json = """
[
    {
        "person": "Jack",
        "allowdate": "March 26th 2020",
        "ready_time": "10:00 am"
    },
    {
        "person": "Jill",
        "allowdate": "January 1st 2020",
        "ready_time": "1:00 pm"
    },
    {
        "person": "Don",
        "allowdate": "January 10th 2020",
        "ready_time": "1:25 pm"
    }
]
"""

struct TableStructure: Decodable {
    // These first three come frm the json
    let person: String
    let allowdate: String
    let readyTime: String
    // We'll calculate this one later
    let compareDate: Date

    // This date formatter will read in dates like "January 10th 2020"
    // So to use this, we will need to pull the ordinal letters off first
    static let dateFormatter: DateFormatter = {
        let dateFormatter = DateFormatter()
        dateFormatter.dateFormat = "MMM dd yyyy"
        return dateFormatter
    }()

    enum DecodeError: Error {
        case compareDateError
    }

    enum CodingKeys: String, CodingKey {
        case person
        case allowdate
        case readyTime
    }

    // We decode the three key/values that are passed down, and we calculate a date that we can use to compare
    init(from decoder: Decoder) throws {
        let values = try decoder.container(keyedBy: CodingKeys.self)
        person = try values.decode(String.self, forKey: .person)
        readyTime = try values.decode(String.self, forKey: .readyTime)
        allowdate = try values.decode(String.self, forKey: .allowdate)

        if let date = TableStructure.comparingDate(from: allowdate) {
            compareDate = date
        } else {
            throw DecodeError.compareDateError
        }

    }

    // We pull the ordinal letters off of the date, and are left with something cleaner
    // A regex could make this much simpler, but me and regex's, we don't get along so great
    static func comparingDate(from dateString: String) -> Date? {
        var datePurgedArray = dateString.split(separator: " ")
        if datePurgedArray.count == 3 {
            datePurgedArray[1] = datePurgedArray[1].filter("0123456789.".contains)
            let newDateString = datePurgedArray.joined(separator:" ")
            print(newDateString)
            return TableStructure.dateFormatter.date(from: newDateString)
        } else {
            return nil
        }
    }

}

if let jsonData = json.data(using: .utf8) {
    print("json Data is \(jsonData)")
    do {
        let decoder = JSONDecoder()
        decoder.keyDecodingStrategy = .convertFromSnakeCase
        let array = try decoder.decode([TableStructure].self, from: jsonData).sorted { $0.compareDate < $1.compareDate }

        print("array is \(array)")
    } catch {
        print(error.localizedDescription + "could not decode array")
    }
} else {
    print("could not get data from json")
}

推荐阅读