Нужна помощь в построении модели данных для периодов времени - PullRequest
2 голосов
/ 05 мая 2019

Я создаю приложение, которое предлагает услугу с чем-то похожим на выгула собак.Люди, которые будут выгуливать собак, могут загружать дни и время, когда они доступны.Вместо того, чтобы они выбирали реальную дату, такую ​​как понедельник, 1-е января, я позволил им просто выбирать любые дни недели и любое время, когда они были в наличии.

Проблема, с которой я столкнулся, заключается в том, что я не могу понять, как построитьмодель данных для него.

На фотографии представлен коллекционный вид с ячейкой, и в каждой ячейке я показываю доступные слоты для дня и времени, которые они могут выбрать.Каждый день недели имеет те же 7 временных интервалов, которые может выбрать пользователь, который хочет быть собачником.

Дело в том, что кто-то выбирает вс 6: 6-9: 00, 12: 00–13: 00 и 18: 00–21: 00.но они также выбирают пн 6 утра-9м, как я могу построить модель данных, которая может различать дни и время.Например, в воскресенье в 6 утра - 9 утра и в понедельник 6 утра - 9 утра, как определить разницу?Должны ли эти временные интервалы быть Doubles или Strings?

Это то, что я сейчас использую для источника данных 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
}

Для небольшого дальнейшего объяснения того, что в конечном итоге произойдетэто когда пользователь, который хочет, чтобы его собака гуляла, прокручивал список, чтобы увидеть, кто ему помогает, если день и время его прокрутки не относятся ни к одному из дней и времен, когда человек, который отправил сообщение (Sun & Mon с выбранными часами), неесли сообщение доступно, то его сообщение не должно появляться в ленте, но если это один из тех дней и один из этих часов, то его публикация будет отображаться в ленте (в примере, если кто-то просматривает воскресенье в 22:00, это сообщение не должнопоявляются).Все, что находится в модели данных, будет сравниваться с тем днем ​​и временем, когда посты в настоящее время прокручиваются.Я использую 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 он дал мне некоторое представление о внесении некоторых изменений в мой код.Я все еще перевариваю это, но у меня все еще есть пара проблем.Он сделал крутой проект, который показывает его идею.

1- Поскольку я сохраняю данные в базе данных Firebase, как эти данные должны быть структурированы, чтобы их сохранить?Может быть несколько дней с одинаковым временем.

2- Я все еще обдумываю код роба, потому что раньше никогда не имел дело с временными диапазонами, так что это мне чуждо.Я все еще теряюсь в том, с чем сравнивать, особенно с временными интервалами внутри обратного вызова

Ответы [ 2 ]

4 голосов
/ 05 мая 2019

Есть много способов снять шкуру с кошки, но я мог бы определить доступность как подсчет дня и диапазон времени:

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
}

Это плюсы и минусы как Int, так и String.Строковое представление легче читать в веб-интерфейсе Firestore.Целочисленное представление предлагает более легкий потенциал сортировки.

Ваш временной диапазон:

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)
    }
}
0 голосов
/ 05 мая 2019

Я бы посоветовал доступность магазина в более общем виде, чем позволяет ваш пользовательский интерфейс.Это позволяет вам менять свой интерфейс без огромных трудностей.Я бы сохранил его как массив доступных времен.Каждое доступное время будет содержать день недели, время начала и время окончания.

...