【问题标题】:Tableviewcells into specific header sections by classification (iOS)按分类将表格视图单元格放入特定的标题部分(iOS)
【发布时间】:2017-02-07 15:19:19
【问题描述】:

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

示例

实施

看看顶部有一个今天和昨天的标题部分,旁边是日期寒冷吗?我问过同行,其中一些人建议尝试 [[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.....

结论

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

【问题讨论】:

  • 您可以通过在项目中创建 json 文件并使用该数据源来设置所有这些数据,而不是创建这些多个枚举、数组和字典。主要是它也很容易管理。

标签: ios swift uitableview enums


【解决方案1】:

正如您正确推断的那样,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
*/

您现在可以使用sections 驱动您的UITableViewDataSource。例如:

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
}

【讨论】:

  • 感谢您提供非常详细的评论!我会尝试实施,然后回复您!
  • 不客气!数据结构设计中一个有趣的小问题!我敢肯定这不是唯一的解决方案......
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-03-11
  • 2020-03-16
  • 1970-01-01
  • 2018-12-26
相关资源
最近更新 更多