'Compare Times to get active time from data

Simulator Screenshot

In the example above, I have a data model that contains various times for an Itinerary that will be displayed. I would like to highlight the current time with a filled circle:

struct SampleModel: Identifiable {
let id = UUID()
let title: String
let description: String
let time: Date
let icon: String

}

let timeInterval = 1652619600

class Sample: ObservableObject {
    @Published var sample2 = [SampleModel(title: "Coffee", description: "Get coffee", time: Date(timeIntervalSince1970: TimeInterval(timeInterval)), icon: "house"),
                              SampleModel(title: "Coffee", description: "Get coffee", time: Date(timeIntervalSince1970: TimeInterval(timeInterval)).adding(minutes: 30), icon: "house"),
                              SampleModel(title: "Dinner", description: "Outback Steakhouse", time: Date(timeIntervalSince1970: TimeInterval(timeInterval)).adding(minutes: 60), icon: "person"),
                              SampleModel(title: "Check Weather", description: "Use app to check weather", time: Date(timeIntervalSince1970: TimeInterval(timeInterval)).adding(minutes: 120), icon: "cloud.sun.fill"),
                              SampleModel(title: "Go To Work", description: "Leave for work", time: Date(timeIntervalSince1970: TimeInterval(timeInterval)).adding(minutes: 180), icon: "car.fill"),
                              SampleModel(title: "YouTube", description: "Watch youtube video", time: Date(timeIntervalSince1970: TimeInterval(timeInterval)).adding(minutes: 240), icon: "video.fill"),
                              SampleModel(title: "Cut Grass", description: "Work in yard", time: Date(timeIntervalSince1970: TimeInterval(timeInterval)).adding(minutes: 300), icon: "speedometer"),
                              SampleModel(title: "Ride Bike", description: "Go to the trace", time: Date(timeIntervalSince1970: TimeInterval(timeInterval)).adding(minutes: 360), icon: "bicycle"),
                              SampleModel(title: "Take Pictures", description: "Photograph the moon", time: Date(timeIntervalSince1970: TimeInterval(timeInterval)).adding(minutes: 420), icon: "camera.fill"),
                              SampleModel(title: "Boat Ride", description: "Go boating", time: Date(timeIntervalSince1970: TimeInterval(timeInterval)).adding(minutes: 480), icon: "ferry.fill"),
                              SampleModel(title: "Colorado trip", description: "Fly to Erie", time: Date(timeIntervalSince1970: TimeInterval(timeInterval)).adding(minutes: 540), icon: "airplane")]
    
    func isCurrent(date1: Date) -> Bool {
        var currentItem: Bool = false
        
        for cTime in sample2 {
            if date1 <= cTime.time  && date1 <= Date()  {
            } else {
                currentItem = false
            }
        }
        return currentItem
    }
}

The data above is just a sample mock data so I can get the UI and the functioning working properly. In my content view I have. foreach loop on the sample data, and I want to highlight the current item with a filled circle. In the isCurrent() function, I can get all items that already have occurred before, but I want to return the most recent.

ForEach(sampleVM.sample2, id: \.id) { index in
        Divider()
        ItemRowView(isCurrent: sampleVM.isCurrent(date1: index.time), isLastRow: lastRow(item: index.id), time: Date(), sample: index)
}

ItemRowView() is what I am using to display the data.



Solution 1:[1]

As the array is sorted you simply need to find the first item/index whose date is greater than the current date

  • If the index is not found (current date is later than the date of the last item) the item is the last item
  • If the index is 0 (current date is sooner than the date of the first item) the item is nil
  • Otherwise the item is the item at index - 1

let currentItem : SampleModel?
if let nextIndex = sample2.firstIndex(where: {$0.time > Date()}) {
    currentItem = nextIndex > 0 ? sample2[nextIndex - 1] : nil
} else {
    currentItem = sample2.last!
}

Or if the result is the index

let currentIndex: Int?
if let nextIndex = sample2.firstIndex(where: {$0.time > Date()}) {
    currentIndex = nextIndex > 0 ? nextIndex - 1 : nil
} else {
    currentIndex = sample2.endIndex - 1
}

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1