草庐IT

ios - 为时间段构建数据模型

coder 2023-09-13 原文

我正在构建一个应用程序,提供类似于遛狗的服务。遛狗的人可以上传可以遛狗的日期和时间。我没有让他们选择像 1 月 1 日星期一这样的实际日期,而是让他们选择一周中的任何几天以及他们有空的任何时间。

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

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

问题是,如果有人选择周日上午 6 点至上午 9 点、中午 2 点至下午 3 点和下午 6 点至晚上 9 点,但他们还选择周一上午 6 点至 9 点,我该如何构建一个可以区分日期和时间的数据模型。例如星期天早上 6 点到 9 点和星期一早上 6 点到 9 点,如何区分?这些时间段应该是 double 还是字符串?

这是我目前用于 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
}

进一步解释一下,当想要遛狗的用户滚动查看谁有空时,如果他们滚动的日期和时间不在发布者的任何日期和时间上,最终会发生什么(周日和周一的所选时间)不可用,那么他们的帖子不应出现在提要中,但如果是那些日子和其中一个小时,那么他们的帖子将出现在提要中(在示例中,如果有人在周日晚上 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 数据源,它们都必须是相同的数据类型。

更新 在@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)
}

最佳答案

给猫皮的方法有很多种,但我可能会将可用性定义为日期枚举和时间范围:

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 基于网络的 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)
    }
}

关于ios - 为时间段构建数据模型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55989075/

有关ios - 为时间段构建数据模型的更多相关文章

  1. ruby-on-rails - Rails - 子类化模型的设计模式是什么? - 2

    我有一个模型:classItem项目有一个属性“商店”基于存储的值,我希望Item对象对特定方法具有不同的行为。Rails中是否有针对此的通用设计模式?如果方法中没有大的if-else语句,这是如何干净利落地完成的? 最佳答案 通常通过Single-TableInheritance. 关于ruby-on-rails-Rails-子类化模型的设计模式是什么?,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.co

  2. ruby - 解析 RDFa、微数据等的最佳方式是什么,使用统一的模式/词汇(例如 schema.org)存储和显示信息 - 2

    我主要使用Ruby来执行此操作,但到目前为止我的攻击计划如下:使用gemsrdf、rdf-rdfa和rdf-microdata或mida来解析给定任何URI的数据。我认为最好映射到像schema.org这样的统一模式,例如使用这个yaml文件,它试图描述数据词汇表和opengraph到schema.org之间的转换:#SchemaXtoschema.orgconversion#data-vocabularyDV:name:namestreet-address:streetAddressregion:addressRegionlocality:addressLocalityphoto:i

  3. ruby-on-rails - Rails - 一个 View 中的多个模型 - 2

    我需要从一个View访问多个模型。以前,我的links_controller仅用于提供以不同方式排序的链接资源。现在我想包括一个部分(我假设)显示按分数排序的顶级用户(@users=User.all.sort_by(&:score))我知道我可以将此代码插入每个链接操作并从View访问它,但这似乎不是“ruby方式”,我将需要在不久的将来访问更多模型。这可能会变得很脏,是否有针对这种情况的任何技术?注意事项:我认为我的应用程序正朝着单一格式和动态页面内容的方向发展,本质上是一个典型的网络应用程序。我知道before_filter但考虑到我希望应用程序进入的方向,这似乎很麻烦。最终从任何

  4. ruby-on-rails - 在混合/模块中覆盖模型的属性访问器 - 2

    我有一个包含模块的模型。我想在模块中覆盖模型的访问器方法。例如:classBlah这显然行不通。有什么想法可以实现吗? 最佳答案 您的代码看起来是正确的。我们正在毫无困难地使用这个确切的模式。如果我没记错的话,Rails使用#method_missing作为属性setter,因此您的模块将优先,阻止ActiveRecord的setter。如果您正在使用ActiveSupport::Concern(参见thisblogpost),那么您的实例方法需要进入一个特殊的模块:classBlah

  5. ruby-on-rails - 如何验证非模型(甚至非对象)字段 - 2

    我有一个表单,其中有很多字段取自数组(而不是模型或对象)。我如何验证这些字段的存在?solve_problem_pathdo|f|%>... 最佳答案 创建一个简单的类来包装请求参数并使用ActiveModel::Validations。#definedsomewhere,atthesimplest:require'ostruct'classSolvetrue#youcouldevencheckthesolutionwithavalidatorvalidatedoerrors.add(:base,"WRONG!!!")unlesss

  6. ruby-on-rails - form_for 中不在模型中的自定义字段 - 2

    我想向我的Controller传递一个参数,它是一个简单的复选框,但我不知道如何在模型的form_for中引入它,这是我的观点:{:id=>'go_finance'}do|f|%>Transferirde:para:Entrada:"input",:placeholder=>"Quantofoiganho?"%>Saída:"output",:placeholder=>"Quantofoigasto?"%>Nota:我想做一个额外的复选框,但我该怎么做,模型中没有一个对象,而是一个要检查的对象,以便在Controller中创建一个ifelse,如果没有检查,请帮助我,非常感谢,谢谢

  7. ruby-on-rails - 如何将验证与模型分开 - 2

    我有一些非常大的模型,我必须将它们迁移到最新版本的Rails。这些模型有相当多的验证(User有大约50个验证)。是否可以将所有这些验证移动到另一个文件中?说app/models/validations/user_validations.rb。如果可以,有人可以提供示例吗? 最佳答案 您可以为此使用关注点:#app/models/validations/user_validations.rbrequire'active_support/concern'moduleUserValidationsextendActiveSupport:

  8. ruby-on-rails - Rails 模型——非持久类成员或属性? - 2

    对于Rails模型,是否可以/建议让一个类的成员不持久保存到数据库中?我想将用户最后选择的类型存储在session变量中。由于我无法从我的模型中设置session变量,我想将值存储在一个“虚拟”类成员中,该成员只是将值传递回Controller。你能有这样的类(class)成员吗? 最佳答案 将非持久属性添加到Rails模型就像任何其他Ruby类一样:classUser扩展解释:在Ruby中,所有实例变量都是私有(private)的,不需要在赋值前定义。attr_accessor创建一个setter和getter方法:classUs

  9. ruby-on-rails - Ruby 检查日期时间是否为 iso8601 并保存 - 2

    我需要检查DateTime是否采用有效的ISO8601格式。喜欢:#iso8601?我检查了ruby​​是否有特定方法,但没有找到。目前我正在使用date.iso8601==date来检查这个。有什么好的方法吗?编辑解释我的环境,并改变问题的范围。因此,我的项目将使用jsapiFullCalendar,这就是我需要iso8601字符串格式的原因。我想知道更好或正确的方法是什么,以正确的格式将日期保存在数据库中,或者让ActiveRecord完成它们的工作并在我需要时间信息时对其进行操作。 最佳答案 我不太明白你的问题。我假设您想检查

  10. ruby-on-rails - Rails - 从另一个模型中创建一个模型的实例 - 2

    我有一个正在构建的应用程序,我需要一个模型来创建另一个模型的实例。我希望每辆车都有4个轮胎。汽车模型classCar轮胎模型classTire但是,在make_tires内部有一个错误,如果我为Tire尝试它,则没有用于创建或新建的activerecord方法。当我检查轮胎时,它没有这些方法。我该如何补救?错误是这样的:未定义的方法'create'forActiveRecord::AttributeMethods::Serialization::Tire::Module我测试了两个环境:测试和开发,它们都因相同的错误而失败。 最佳答案

随机推荐