Tableview按分类(iOS)

时间:2017-02-07 15:19:20

标签: ios swift uitableview enums

我正在构建一个涉及相当复杂的表视图的辅助项目。我决定从Producthunt的应用程序中获取灵感,每个日期都有一个标题部分。 但是唉,这个简单的实现比我想象的要难一点。作为参考,我在下面附上照片,向您展示我正在尝试克隆的内容。这是来自PH的应用程序:

实施例

header view one header view two

实施

看看顶部有一个今天和昨天标题部分,旁边有日期寒冷吗?我问过同行,其中一些建议尝试[[array]](数组内部的数组)方法。通过枚举将它们分组并将它们放入特定的数组中吗?这很好,但过了一段时间,你可以看到它失控。例如,下面是我的一些代码:

首先,有一个不同日期案例的枚举

enum dateCases {
    case today
    case yesterday
    case twoDaysAgo
    case threeDaysAgo
    case fourDaysAgo
    case fiveDaysAgo
    case lastWeek
    case lastMonth
    case lastYear
    case janurary
    case feburary
    case march
    case april
    case may
    case june
    case july
    case augest
    case september
    case october
    case november
    case december
}

然后每个类都有一个结构,需要这些数组:

struct dateCaseController {
    var todayArray = [Objects]()
    var yesterdayArray = [Objects]()
    var twoDaysAgoArray = [Objects]()
    var threeDaysAgoArray = [Objects]()
    var fourDaysAgoArray = [Objects]()
    var fiveDaysAgoArray = [Objects]()
    var lastWeekArray = [Objects]()
    var lastMonthArray = [Objects]()
    var lastYearArray = [Objects]()
    var januraryArray = [Objects]()
    var feburaryArray = [Objects]()
    var marchArray = [Objects]()
    var aprilArray = [Objects]()
    var mayArray = [Objects]()
    var juneArray = [Objects]()
    var julyArray = [Objects]()
    var augestArray = [Objects]()
    var septemberArray = [Objects]()
    var octoberArray = [Objects]()
    var novemberArray = [Objects]()
    var decemberArray = [Objects]()
}

对象都有日期,我们可以使用它来分析和分割数据。这个类的每个实例都有这个结构。

在完成所有这些之后,有一个功能可以将不同的对象划分为特定的数组:

 func anilyzeDateForDateCase(){
        for object in objects {
            let dateValue = (Logic for counting how many days has passed)

            switch dateValue {
            case 0:
                print("")
            case 1:
                print("")
            case 2:
                print("")
            case 3:
                print("")
            case 4:
                print("")
            case 5:
                print("")
            case 6:
                print("")
            ect.....

结论

这将是很多切换案例。你可以通过这种方法来判断代码是否会失控。如果我有少量类别,使用这种方法会很好,但事实并非如此。更不用说在那之后,我将根据部分加载表数组。我这样做很好,但我想知道这是否是解决这个问题的正确方法?必须有一个更简单的解决方案。有没有人有这样的实现经验?谢谢。

1 个答案:

答案 0 :(得分:3)

正如您正确推断的那样,enum 不是的方式。除了其他任何东西,它都是将UI选择硬编码到您的数据结构中。

我可以提出以下建议吗:

import Foundation

// Define a `struct` that describes a date range.
// You may want to have convenience inits that don't just specify "days ago".
// You will create an array of these later...
struct DateRange {
    var latestDaysAgo: Int
    var earliestDaysAgo: Int
    var description: String

    // The important piece of this is that we can check if any given date 
    // is in `self` - we will use this later to `filter` by DateRange
    func isDateInRange(_ date: Date) -> Bool {
        let now = Date()
        let oneDayInSeconds = 86400.0 // 60 * 60 * 24
        let earliestDate = now.addingTimeInterval(Double(-self.earliestDaysAgo) * oneDayInSeconds)
        let latestDate = now.addingTimeInterval(Double(-self.latestDaysAgo) * oneDayInSeconds)
        return (date > earliestDate) && (date <= latestDate)
        // NB - you REALLY want to do this with `Calendar` arithmetic
        // but for clarity of the method, I'm just using 24 hour time differences
    }
}

// Now construct your ranges. These can be extended after testing.
// They can also be overlapping.
let ranges: [DateRange] = [
    DateRange(latestDaysAgo: 0, earliestDaysAgo: 1, description: "Today"),
    DateRange(latestDaysAgo: 1, earliestDaysAgo: 2, description: "Yesterday"),
    DateRange(latestDaysAgo: 2, earliestDaysAgo: Int.max, description: "Earlier"),
]

// This is whatever event struct you need - but they include the date
struct Event {
    var date: Date
    var payload: String // or whatever struct you want
}
// Create some random test data
let events: [Event]  = [
    Event(date: Date().addingTimeInterval(-100), payload: "abc"),
    Event(date: Date().addingTimeInterval(-1000), payload: "abc"),
    Event(date: Date().addingTimeInterval(-100000), payload: "abc"),
    Event(date: Date().addingTimeInterval(-1000000), payload: "abc"),
]

// Now, the clever piece is combining `flatMap` & `filter` to get your sections:
let sections: [(DateRange, [Event])] = ranges.flatMap({
    (dr: DateRange) in
    let qualifyingEvents = events.filter({ dr.isDateInRange($0.date) })
    return (dr, qualifyingEvents)
})
// Note that the order of ranges in `sections` is the same as the 
// order that you chose in `ranges`.

// Check the sections are correct.
for (dr, es) in sections {
    print("'\(dr.description)' has \(es.count) entries")
}

/* Output:
 'Today' has 2 entries
 'Yesterday' has 1 entries
 'Earlier' has 1 entries
*/

您现在可以使用UITableViewDataSource驾驶sections。例如:

override func numberOfSections(in tableView: UITableView) -> Int {
    return sections.count
}

override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    return sections[section].1.count
}

override func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
    return sections[section].0.description
}

override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = UITableViewCell(style: .subtitle, reuseIdentifier: "MyCellID")

    let payload = sections[indexPath.section].1[indexPath.row].payload

    cell.textLabel?.text = payload // or whatever...
    return cell
}