需要帮助构建时间段的数据模型

时间:2019-05-05 05:25:16

标签: ios swift class datamodel

我正在构建一个提供类似于dog狗的服务的应用程序。 walk狗的人可以上传有空的日期和时间。与其让他们选择像1月1日星期一这样的实际日期,不如让他们选择他们在星期几,什么时候可用。

我遇到的问题是我不知道如何为它构造数据模型。

照片中的是一个带有一个单元格的collectionView,在每个单元格中,我显示了他们可以选择的可用日期和时段。一周中的每一天都有相同的7个时隙,想要成为walk狗者的用户可以从中选择。

问题是,如果有人选择早上6点至上午9点,12 pm-3pm和6 pm-9pm星期日,但他们也选择了上午6点至9m,则该如何构建可以区分日期和时间的数据模型。例如,周日上午6点至上午9点以及周一上午6点至上午9点,如何区分两者之间的差异?这些时隙应该是双精度还是字符串?

这是我当前用于collectionView数据源和单元格的内容:

// the collectionView's data source
var tableData = ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"]

//cellForItem
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: availabilityCell, for: indexPath) as! AvailabilityCell

cell.clearCellForReuse()
cell.dayOfWeek = tableData[indexPath.item]

// inside the AvailabilityCell itself
var dayOfWeek: String? {
    didSet {

        dayOfWeekLabel.text = dayOfWeek
    }
}

func clearCellForReuse() {

    dayOfWeekLabel.text = nil
    // deselect whatever radio buttons were selected to prevent scrolling issues
}

为进一步解释,最终将要发生的事情是,如果希望其狗dog着的用户滚动查看谁有空,如果滚动的日期和时间不在发布者的日期和时间中(具有选定小时数的星期日和星期一)不可用,那么它们的帖子就不会出现在供稿中,但是如果是那一天中的某一天和那几个小时之一,那么他们的帖子就会出现在供稿中(在示例中,如果某人在周日晚上10点滚动,此帖子不应显示)。数据模型中的任何内容都将与当前滚动帖子的日期和时间进行比较。我在后端使用Firebase。

我的想法很复杂,这就是为什么我需要更合理的东西。

class Availability {

    var monday: String?
    var tuesday: String?
    var wednesday: String?
    var thursday: String?
    var friday: String?
    var saturday: String?
    var sunday: String?

    var slotOne: Double? // sunday 6am-9am I was thinking about putting military hours  here that's why I used a double
    var slotTwo: Double? // sunday 9am-12pm
    var slotTwo: Double? // sunday 12pm-3pm
    // these slots would continue all through saturday and this doesn't seem like the correct way to do this. There would be 49 slots in total (7 days of the week * 7 different  slots per day)
}

我还考虑过将它们分成不同的数据模型,例如星期一类,星期二类等,但这似乎也不起作用,因为它们对于collectionView数据源都必须是相同的数据类型。

enter image description here

更新 在@rob的回答中,他给了我一些见识,可以对我的代码进行一些更改。我仍在消化它,但仍然有一些问题。他做了cool project that shows his idea.

1-由于我要将数据保存到Firebase数据库中,因此应该如何结构化数据以进行保存?可能会有几天时间相似。

2-我仍在围绕rob的代码,因为我之前从未处理过时间范围,所以这对我来说很陌生。我仍然不知道该如何针对回调进行排序,尤其是针对回调内部的时间范围

// someone is looking for a dog walker on Sunday at 10pm so the initial user who posted their post shouldn't appear in the feed

let postsRef = Database().database.reference().child("posts")

postsRef.observe( .value, with: { (snapshot) in

    guard let availabilityDict = snapshot.value as? [String: Any] else { return }

    let availability = Availability(dictionary: availabilityDict)

    let currentDayOfWeek = dayOfTheWeek()

    // using rob;s code this compares the days and it 100% works
    if currentDayOfWeek != availability.dayOfWeek.text {

        // don't add this post to the array
        return
    }

    let currentTime = Calendar.current.dateComponents([.hour,.minute,.second], from: Date())

    // how to compare the time slots to the current time?
    if currentTime != availability.??? {
        // don't add this post to the array
        return
    }

    // if it makes this far then the day and the time slots match up to append it to the array to get scrolled
})

func dayOfTheWeek() -> String? {        
    let dateFormatter = NSDateFormatter()
    dateFormatter.dateFormat = "EEEE"
    return dateFormatter.stringFromDate(self)
}

2 个答案:

答案 0 :(得分:4)

有很多方法可以给猫咪剥皮,但是我可以将可用性定义为日计数和时间范围:

struct Availability {
    let dayOfWeek: DayOfWeek
    let timeRange: TimeRange
}

您星期几可能是:

enum DayOfWeek: String, CaseIterable {
    case sunday, monday, tuesday, wednesday, thursday, friday, saturday
}

或者您也可以这样做:

enum DayOfWeek: Int, CaseIterable {
    case sunday = 0, monday, tuesday, wednesday, thursday, friday, saturday
}

它们是IntString的优缺点。在Firestore基于Web的UI中,字符串表示形式更易于阅读。整数表示形式提供了更容易的排序潜力。

您的时间范围:

typealias Time = Double
typealias TimeRange = Range<Time>

extension TimeRange {
    static let allCases: [TimeRange] = [
        6 ..< 9,
        9 ..< 12,
        12 ..< 15,
        15 ..< 18,
        18 ..< 21,
        21 ..< 24,
        24 ..< 30
    ]
}

就与Firebase的交互而言,它不了解枚举和范围,因此我将定义一个init方法和一个dictionary属性,以与往返于[String: Any]字典的对象进行映射您可以与Firebase交换:

struct Availability {
    let dayOfWeek: DayOfWeek
    let timeRange: TimeRange

    init(dayOfWeek: DayOfWeek, timeRange: TimeRange) {
        self.dayOfWeek = dayOfWeek
        self.timeRange = timeRange
    }

    init?(dictionary: [String: Any]) {
        guard
            let dayOfWeekRaw = dictionary["dayOfWeek"] as? DayOfWeek.RawValue,
            let dayOfWeek = DayOfWeek(rawValue: dayOfWeekRaw),
            let startTime = dictionary["startTime"] as? Double,
            let endTime = dictionary["endTime"] as? Double
        else {
            return nil
        }

        self.dayOfWeek = dayOfWeek
        self.timeRange = startTime ..< endTime
    }

    var dictionary: [String: Any] {
        return [
            "dayOfWeek": dayOfWeek.rawValue,
            "startTime": timeRange.lowerBound,
            "endTime": timeRange.upperBound
        ]
    }
}

您还可以定义一些扩展名,以使其更易于使用,例如

extension Availability {
    func overlaps(_ availability: Availability) -> Bool {
        return dayOfWeek == availability.dayOfWeek && timeRange.overlaps(availability.timeRange)
    }
}

extension TimeRange {
    private func string(forHour hour: Int) -> String {
        switch hour % 24 {
        case 0:      return NSLocalizedString("Midnight", comment: "Hour text")
        case 1...11: return "\(hour % 12)" + NSLocalizedString("am", comment: "Hour text")
        case 12:     return NSLocalizedString("Noon", comment: "Hour text")
        default:     return "\(hour % 12)" + NSLocalizedString("pm", comment: "Hour text")
        }
    }

    var text: String {
        return string(forHour: Int(lowerBound)) + "-" + string(forHour: Int(upperBound))
    }
}

extension DayOfWeek {
    var text: String {
        switch self {
        case .sunday:    return NSLocalizedString("Sunday", comment: "DayOfWeek text")
        case .monday:    return NSLocalizedString("Monday", comment: "DayOfWeek text")
        case .tuesday:   return NSLocalizedString("Tuesday", comment: "DayOfWeek text")
        case .wednesday: return NSLocalizedString("Wednesday", comment: "DayOfWeek text")
        case .thursday:  return NSLocalizedString("Thursday", comment: "DayOfWeek text")
        case .friday:    return NSLocalizedString("Friday", comment: "DayOfWeek text")
        case .saturday:  return NSLocalizedString("Saturday", comment: "DayOfWeek text")
        }
    }
}

如果您不想使用Range,只需将TimeRange定义为struct

enum DayOfWeek: String, CaseIterable {
    case sunday, monday, tuesday, wednesday, thursday, friday, saturday
}

extension DayOfWeek {
    var text: String {
        switch self {
        case .sunday:    return NSLocalizedString("Sunday", comment: "DayOfWeek text")
        case .monday:    return NSLocalizedString("Monday", comment: "DayOfWeek text")
        case .tuesday:   return NSLocalizedString("Tuesday", comment: "DayOfWeek text")
        case .wednesday: return NSLocalizedString("Wednesday", comment: "DayOfWeek text")
        case .thursday:  return NSLocalizedString("Thursday", comment: "DayOfWeek text")
        case .friday:    return NSLocalizedString("Friday", comment: "DayOfWeek text")
        case .saturday:  return NSLocalizedString("Saturday", comment: "DayOfWeek text")
        }
    }
}

struct TimeRange {
    typealias Time = Double

    let startTime: Time
    let endTime: Time
}

extension TimeRange {
    static let allCases: [TimeRange] = [
        TimeRange(startTime: 6, endTime: 9),
        TimeRange(startTime: 9, endTime: 12),
        TimeRange(startTime: 12, endTime: 15),
        TimeRange(startTime: 15, endTime: 18),
        TimeRange(startTime: 18, endTime: 21),
        TimeRange(startTime: 21, endTime: 24),
        TimeRange(startTime: 24, endTime: 30)
    ]

    func overlaps(_ availability: TimeRange) -> Bool {
        return (startTime ..< endTime).overlaps(availability.startTime ..< availability.endTime)
    }
}

extension TimeRange {
    private func string(forHour hour: Int) -> String {
        switch hour % 24 {
        case 0:      return NSLocalizedString("Midnight", comment: "Hour text")
        case 1...11: return "\(hour % 12)" + NSLocalizedString("am", comment: "Hour text")
        case 12:     return NSLocalizedString("Noon", comment: "Hour text")
        default:     return "\(hour % 12)" + NSLocalizedString("pm", comment: "Hour text")
        }
    }

    var text: String {
        return string(forHour: Int(startTime)) + "-" + string(forHour: Int(endTime))
    }
}

struct Availability {
    let dayOfWeek: DayOfWeek
    let timeRange: TimeRange

    init(dayOfWeek: DayOfWeek, timeRange: TimeRange) {
        self.dayOfWeek = dayOfWeek
        self.timeRange = timeRange
    }

    init?(dictionary: [String: Any]) {
        guard
            let dayOfWeekRaw = dictionary["dayOfWeek"] as? DayOfWeek.RawValue,
            let dayOfWeek = DayOfWeek(rawValue: dayOfWeekRaw),
            let startTime = dictionary["startTime"] as? Double,
            let endTime = dictionary["endTime"] as? Double
        else {
            return nil
        }

        self.dayOfWeek = dayOfWeek
        self.timeRange = TimeRange(startTime: startTime, endTime: endTime)
    }

    var dictionary: [String: Any] {
        return [
            "dayOfWeek": dayOfWeek.rawValue,
            "startTime": timeRange.startTime,
            "endTime": timeRange.endTime
        ]
    }
}

extension Availability {
    func overlaps(_ availability: Availability) -> Bool {
        return dayOfWeek == availability.dayOfWeek && timeRange.overlaps(availability.timeRange)
    }
}

答案 1 :(得分:0)

我建议以比您的UI允许的更通用的方式来存储商店。这使您可以轻松更改UI。我会将其存储为可用时间数组。每个availablTime将包含一周中的一天,开始时间和结束时间。