Как условно разделить модель данных в UITableView?

У меня есть объект модели, возвращаемый в JSON из Firebase.

{
    "id": 1,
    "name": "Jon Doe",
    "time": ["1525592246"]
},
{
    "id": 2,
    "name": "Jane Doe",
    "time": ["1525592266"]
},

Я хотел бы структурировать эти объекты в разделы в UITableView на основе следующего:

enum DiarySectionType {
    case Today
    case Tomorrow
    case ThisWeek
    case ThisMonth
    case Later
}

То есть, если «время» сегодня, оно будет в сегодняшнем разделе UITableView.

Как лучше всего подойти к этому? Я думал о том, чтобы иметь отдельные массивы для каждого. Но не думайте, что это правильный путь.

Как всегда приветствуется любая помощь.


person David Lintin    schedule 06.05.2018    source источник


Ответы (1)


Сначала вам нужно вспомогательное расширение для вашей даты

extension Date {

    public func component(_ component: Calendar.Component) -> Int {
        let calendar = Calendar.autoupdatingCurrent
        return calendar.component(component, from: self)
    }

    public var isToday: Bool {
        let calendar = Calendar.autoupdatingCurrent
        return calendar.isDateInToday(self)
    }

    public var isTomorrow: Bool {
        let calendar = Calendar.autoupdatingCurrent
        return calendar.isDateInTomorrow(self)
    }

    public var isThisWeek: Bool {
        return isInSameWeek(date: Date())
    }
    public var isThisMonth: Bool {
        return isInSameMonth(date: Date())
    }
    public var islater: Bool {
       return isInSameMonth(date: Date()) ? false : true
    }

}
extension Date {
    func isInSameWeek(date: Date) -> Bool {
        return Calendar.current.isDate(self, equalTo: date, toGranularity: .weekOfYear)
    }
    func isInSameMonth(date: Date) -> Bool {
        return Calendar.current.isDate(self, equalTo: date, toGranularity: .month)
    }
}

Тогда ваш Enum

enum DiarySectionType:Int{
    case Today
    case Tomorrow
    case ThisWeek
    case ThisMonth
    case Later
    case count // use for number of section
    init (with date:Date){

        if date.isToday {
            self = .Today
        }else if date.isTomorrow{
             self = .Tomorrow
        }else if date.isThisWeek{
            self = .ThisWeek
        }else if date.isThisMonth{
             self = .ThisMonth
        }else{
           self = .Later
        }
    }
}

Ваши данные Формализуйте как вам нужно

struct Item{
    var id : Int
    var name : String
    var time : Double
    init(id:Int, name:String,time:Double) {

        self.id = id
        self.name = name
        self.time = time
    }
}

// Контроллер

  class  ViewController: UIViewController{

          var data = [Item]() // your data before sections
          var dataWork = [DiarySectionType: [Item]]() // date After sections

        override func viewDidLoad() {
            super.viewDidLoad()

            self.sortData()

          }

   // When generating sorted table data we can easily use our TableSection to make look up simple and easy to read.
        func sortData() {
            dataWork[.Today] = data.filter({ DiarySectionType.init(with: Date.init(timeIntervalSince1970: $0.time))  == .Today })
            dataWork[.Tomorrow] = data.filter({ DiarySectionType.init(with: Date.init(timeIntervalSince1970: $0.time))  == .Tomorrow })
            dataWork[.ThisWeek] = data.filter({ DiarySectionType.init(with: Date.init(timeIntervalSince1970: $0.time))  == .ThisWeek })
            dataWork[.ThisMonth] = data.filter({ DiarySectionType.init(with: Date.init(timeIntervalSince1970: $0.time))  == .ThisMonth })
            dataWork[.Later] = data.filter({ DiarySectionType.init(with: Date.init(timeIntervalSince1970: $0.time))  == .Later })
        }
    }




extension ViewController: UITableViewDataSource, UITableViewDelegate {

    // As long as `count` is the last case in our TableSection enum,
    // this method will always be dynamically correct no mater how many table sections we add or remove.
    func numberOfSections(in tableView: UITableView) -> Int {
        return DiarySectionType.count.rawValue
    }

    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        // Using Swift's optional lookup we first check if there is a valid section of table.
        // Then we check that for the section there is data that goes with.
        if let tableSection = DiarySectionType(rawValue: section), let data = dataWork[tableSection] {
            return data.count
        }
        return 0
    }

    func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
        var title : String = ""
        if let tableSection = DiarySectionType(rawValue: section) {
            switch tableSection {
            case .Today:
                title = "Today"
            case .Tomorrow:
                title = "Tomorrow"
            case .ThisMonth:
                title = "ThisMonth"
            case .ThisWeek:
                title = "ThisWeek"
            case .Later:
                title = "Later"
            default:
                title = ""
            }
        }

        return title
    }


    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath)
        // Similar to above, first check if there is a valid section of table.
        // Then we check that for the section there is a row.
        if let tableSection = DiarySectionType(rawValue: indexPath.section), let item = dataWork[tableSection]?[indexPath.row] {
          // use item item

        }
        return cell
    }

}
person Abdelahad Darwish    schedule 06.05.2018
comment
Спасибо. Можно ли выполнять всю фильтрацию на клиенте/устройстве? Как я буду реализовывать numberOfRowsInSection из этого? - person David Lintin; 06.05.2018
comment
невозможно получить доступ к rawValue - person David Lintin; 06.05.2018
comment
Извините, код обновлен, Enum обновлен, чтобы иметь тип Int @DavidLintin - person Abdelahad Darwish; 06.05.2018
comment
относительно продления даты. Сегодня работает нормально, однако тестирование других создает нарушения. Я использую этот сайт для расчета временных меток. www.epochconverter.com/ При входе на завтра/на этой неделе ячейка появится в конце таблицы. - person David Lintin; 06.05.2018
comment
Хорошо, позвольте мне проверить, но это концепция. Продлить дату легко, я проверю для вас - person Abdelahad Darwish; 06.05.2018
comment
Давайте продолжим обсуждение в чате. - person David Lintin; 06.05.2018