This question already has an answer here:
Setting the TimelineProvider refresh interval for Widget
(1 answer)
Closed 2 years ago.
When I run the code snippet below, WidgetKit is supposed to request a new timeline at the end of each minute according to the Apple's documentation.
Code Block
let currentDate = Date()
let futureDate = Calendar.current.date(byAdding: .minute, value: 1, to: currentDate)!
let timeline = Timeline(entries: [
Entry(date: currentDate, number: Int.random(in: 0...10))], policy: .after(futureDate))
completion(timeline)
But it just works once and nothing happens afterward as if it has been set to .never. I am trying it on iOS 14 Beta 2.
That's because your updates are too aggressive.
Change it to 15 minutes and it will work
Related
For testing purposes, I'm trying to refresh a widget every 30 sec with the following code.
// PWContent is the TimelineEntry object.
func getTimeline(in context: Context, completion: #escaping (Timeline<PWContent>) -> ()) {
NSLog("PWTimelineProvider.getTimeline(in)")
let currentDate: Date = Date.now
let calendar: Calendar = Calendar.current
// Display a random element from the array
let entry: PWContent = PWContent(date: currentDate, planet: PWCustomData.sPlanets.randomElement()!)
NSLog("Current time = " + String(describing: currentDate))
// Set refresh date to 30sec in the future.
let refreshDate = calendar.date(byAdding: .second, value: 30, to: currentDate)!
NSLog("Refresh time = " + String(describing: refreshDate))
let timeline = Timeline(entries: [entry], policy: .after(refreshDate))
completion(timeline)
}
But I get the following logs
PWTimelineProvider.getTimeline(in)
Current time = 2023-01-08 07:53:31 +0000
Refresh time = 2023-01-08 07:54:01 +0000
PWTimelineProvider.getTimeline(in)
Current time = 2023-01-08 07:58:31 +0000
Refresh time = 2023-01-08 07:59:01 +0000
PWTimelineProvider.getTimeline(in)
Current time = 2023-01-08 08:03:31 +0000
Refresh time = 2023-01-08 08:04:01 +0000
As shown in the above logs, the widget refreshes every 5 mins (The difference b/w two 'Current Time'). When checking the Widget in home screen, it doesn't update every 30 sec.
My understanding (which is not what's observed): Widget first updates itself at 7:53:31. When the time is 7:54:01, getTimeline function is invoked (since the refresh policy was set to 7:54:01 i.e. 30 sec later than the previous time) by iOS to request another timeline, which again provides only one entry at the current time (= 7:54:01) and the new refresh policy is set to 7:54:31, which is when getTimeline is invoked again to get the next timeline.
Reference: Provide Timeline Entries section in this wiki.
According to documentation,
WidgetKit imposes a minimum amount of time before it reloads a widget. Your timeline provider should create timeline entries that are at least about 5 minutes apart.
And that's why, despite setting up a refresh period of 30sec, it still refreshes after 5mins.
But, in the following getTimeline(),
// ISWContent is the TimelineEntry object.
func getTimeline(in context: Context, completion: #escaping (Timeline<ISWContent>) -> ()) {
NSLog(ISW_TAG + "ISWTimelineProvider.getTimeline(in)")
let increment: Int = 15
var entries: [ISWContent] = []
let currentDate = Date.now
// Generate a timeline consisting of 4 entries 15 sec apart,
// starting from the current date.
NSLog(ISW_TAG + "Current time = " + String(describing: currentDate))
for index in 0...3 {
let entryDate = Calendar.current.date(byAdding: .second, value: (index * increment), to: currentDate)!
NSLog(ISW_TAG + "incremental dates[%d] = " + String(describing: entryDate), index)
let entry = ISWContent(date: entryDate, state: ISWCustomData.sIndianStates.randomElement()!)
entries.append(entry)
}
let timeline = Timeline(entries: entries, policy: .atEnd)
completion(timeline)
Widget is refreshed every 15secs and once the last timeline entry has expired, getTimeline is invoked immediately to provide the next timeline. The 5mins restriction doesn't apply here.
Anyway, according to documentation, whatever timeline we return, is only a request and may not be granted if the user rarely views the home screen containing the widget or the app.
This question already has an answer here:
SwiftUI iOS 14 Widget CountDown
(1 answer)
Closed 2 years ago.
So I am new to WidgetKit and SwiftUI, but is there an event or a way to detect when the countdown reaches 00:00 for Text()?
let components = DateComponents(minute: 15)
let futureDate = Calendar.current.date(byAdding: components, to: Date())!
Text(futureDate, style: .timer)
It appears that it is either poorly documented -to me at least- or there is still nothing like that..?
It's not possible, when it reaches 0 it will start counting up.
You have to use the timeline to refresh that widget at the end date of your countdown, using a normal Text that just shows 0:00:00
an example:
var entries: [SingleEntry] = []
// First entry at Date() which is now... with the countdown endDate at 60 seconds in the future
// which you'll use in the Text(date, style)
entries.append(
SingleEntry(
date: Date(),
configuration: configuration,
endDate: Date().addingTimeInterval(60)
)
)
// Second entry which will be scheduled at the Date when you want to stop the timer
// in the TimelineEntry now you can check if endDate is nil and use a normale text
// to say that the countdown is over
entries.append(
SingleEntry(
date: Date().addingTimeInterval(60),
configuration: configuration,
endDate: nil
)
)
let timeline = Timeline(entries: entries, policy: .atEnd)
completion(timeline)
This question already has answers here:
Checking response Time of API in iOS using Swift 3?
(4 answers)
Closed 3 years ago.
I'm trying to find a way to tell how long its taken a function to execute in seconds. Currently I'm doing it this way:
let startDate = Date()
let endDate = Date()
let calendar = Calendar.current
let dateComponents = calendar.compare(startDate, to: endDate, toGranularity: .second)
let seconds = dateComponents.rawValue
print("Seconds: \(seconds)")
but every time I print out the seconds it always reads -1. I've looked into this question: elapsed time but I need the output to be in seconds. Any suggestions?
Try this:
let start = Date.timeIntervalSinceReferenceDate
// do stuff
let end = Date.timeIntervalSinceReferenceDate
let secondsElapsed = end - start
secondsElapsed will be a Double, but it will be in seconds. You can round it or truncate it if you want an Int.
Hope this helps!
This question already has answers here:
Getting the difference between two Dates (months/days/hours/minutes/seconds) in Swift
(20 answers)
Closed 5 years ago.
currentCalendar.dateComponents(components: Set Calendar.Component, from: Date, to: Date)
I want to calculate the number of days between 2 dates, I can't seem to find a tutorial anyway online for swift4 Xcode9 everything else seems to be about the outdated syntax. so I just want to know what should I put in the "components: Set Calendar.Component" part ?
You should put a Set of the enumeration type Calendar.Component
example:
let s: Set = [Calendar.Component.day]
let c = Calendar(identifier: .gregorian)
let dc = c.dateComponents(s, from: Date.init(timeIntervalSinceNow: -100000), to: Date.init(timeIntervalSinceNow: 0))
let day = dc.day
the day variable is equal to 1
This question already has answers here:
How to add minutes to current time in swift
(11 answers)
Closed 7 years ago.
How can I reduce 5 or 10 minutes from current time and then store it as date format in Swift 2.0 ?
let now = NSDate()
var reducedTime = ???? \\ Here I want 10 minutes reduced from current time.
If current time is 02:20:00, then reducedTime should be 02:10:00
How can I do this in a simplest way ???
You can use calendar method dateByAddingUnit and subtract 10 minutes fro the date.
let now = NSDate()
let reducedTime = NSCalendar(calendarIdentifier: NSCalendarIdentifierGregorian)?.dateByAddingUnit(.Minute, value: -10, toDate: now, options: NSCalendarOptions())