Below is my function which is not changing the return Value. How do I get the function to return the modified returnVal?
func RecieveActivitySummary() -> HKActivitySummary {
var returnVal = HKActivitySummary()
self.makeQuery() { (summary) in
returnVal = summary //attempting to alter returnVal
print(returnVal) //prints out returnVal object that I want with data (seemingly modified)
}
print(returnVal) //prints out unmodified returnVal
return returnVal //then goes on to return an empty returnVal object
}
Here is my makeQuery() function if it helps address the problem:
func makeQuery(completion: #escaping (_ summary : HKActivitySummary) -> ()) {
let calendar = NSCalendar.current
let endDate = Date()
guard let startDate = calendar.date(byAdding: .day, value: 0, to: endDate) else {
fatalError("error")
}
let units: Set<Calendar.Component> = [.day, .month, .year, .era]
var startDatecomps = calendar.dateComponents(units, from: startDate)
startDatecomps.calendar = calendar
var endDatecomps = calendar.dateComponents(units, from: endDate)
endDatecomps.calendar = calendar
let summariesWithinRange = HKQuery.predicate(forActivitySummariesBetweenStart: startDatecomps, end: endDatecomps)
let query = HKActivitySummaryQuery(predicate: summariesWithinRange) {
(sample, results, error) -> Void in
if let results = results {
var summary = results[0]
completion(summary)
}
}
healthstore.execute(query)
}
Related
I can't find a way to have the makeQuery() function return the summary result. How do I do this? I want to be able to call makeQuery() and have it return summary. summary is an object holding some data. HKActivitySummary to be specific.
func makeQuery() {
let calendar = NSCalendar.current
let endDate = Date()
guard let startDate = calendar.date(byAdding: .day, value: 0, to: endDate) else {
fatalError("error")
}
let units: Set<Calendar.Component> = [.day, .month, .year, .era]
var startDatecomps = calendar.dateComponents(units, from: startDate)
startDatecomps.calendar = calendar
var endDatecomps = calendar.dateComponents(units, from: endDate)
endDatecomps.calendar = calendar
let summariesWithinRange = HKQuery.predicate(
forActivitySummariesBetweenStart: startDatecomps, end: endDatecomps)
let query = HKActivitySummaryQuery(predicate: summariesWithinRange) {
(sample, results, error) -> Void in
if let results = results {
if let summary = results.first {
print(summary) // how to have makeQuery() return the summary value? Just printing it to the console right now to confirm data is being retrieved
}
}
}
healthstore.execute(query)
}
I fail getting 'start' value, tested many variants and formatters. For production reasons cannot use ISO8601DateFormatter.
this code is part of creating appointment on the calendar, so I need start as start date/hour of the appointment.
Above all, I need to understand why this last line of code fails after I tried to convert date:
event.startDate is my 'start' but cannot set it since fails converting date
guard let url = URL(string: "calshow:\(event.startDate.timeIntervalSinceReferenceDate)") else { return }
DispatchQueue.main.async {
UIApplication.shared.open(url, options: [:], completionHandler: nil)
}
my code:
date0
is a Date I get from API, with value 2021-07-28 00:00:00 +0000
my updated code for creating event on calendar
let dateFormatter: DateFormatter = DateFormatter()
dateFormatter.dateFormat = "dd-MM-yyyy HH:mm:ss"
let date = dateFormatter.string(from: date0)
if let startTime = hours.from,
let startDate = date.concats(startTime),
let start = self.shortTimeFormatter.date(from: startDate) {
event.startDate = start
event.addAlarm(EKAlarm(absoluteDate: start.dayBefore))
event.addAlarm(EKAlarm(absoluteDate: start.halfHourBefore))
event.endDate = start.hourAfter
}
if let endTime = hours.to,
let endDate = date.concats(endTime),
let end = self.shortTimeFormatter.date(from: endDate) {
event.endDate = end
}
concats code
func concats(_ string: String, withSeparator separator: String? = "") -> String? {
return [self, string].compactMap{ $0 }.joined(separator: separator! + " ")
}
ShortDateTimeFormatter
public class ShortDateTimeFormatter: DateFormatter {
override public init() {
super.init()
self.dateFormat = "dd/MM/yyyy HH:mm"
}
required public init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
If I understand the code you get a Date without the time portion and you want to add the time in string format "HH:mm:ss".
Calendar can do that. You don't need to convert the Date to String and back to Date.
First create a function which converts the time string to Int components
func timeComponents(from string: String) -> (Int, Int, Int)? {
let comps = string.components(separatedBy: ":")
guard comps.count == 3,
let hr = Int(comps[0]),
let mn = Int(comps[1]),
let sc = Int(comps[2])
else { return nil }
return (hr, mn, sc)
}
Then add the time to date0 with date(bySettingHour:minute:second:of:)
if let (hr, mn, sc) = timeComponents(from: "08:30:00") {
let startDate = Calendar.current.date(bySettingHour: hr, minute: mn, second: sc, of: date0)
}
Or with DateComponents
func timeComponents(from string: String) -> DateComponents? {
let comps = string.components(separatedBy: ":")
guard comps.count == 3,
let hr = Int(comps[0]),
let mn = Int(comps[1]),
let sc = Int(comps[2])
else { return nil }
return DateComponents(hour: hr, minute: mn, second: sc)
}
if let components = timeComponents(from: "08:30:00") {
let startDate = Calendar.current.date(byAdding: components, to: date0, wrappingComponents: false)
}
Issue here is that while from API I get date in this form
Foundation.Date 2021-07-20 00:00:00 UTC
I successfully add hours, with I get start hour from API in form of "08:30:00" with gives me the value for start (but same issue about the end date) this way:
Foundation.Date 2021-07-20 08:30:00 UTC
but, when I get to calendar, the events are set to 10:30 AM, how could I correct the TIME ZONE?
I tested things like
let calendar = Calendar()
calendar.timezone = .current
but did not work
example from response
{
"data": {
"appointments": [
{
"date": "2021-07-20T00:00:00.000Z",
"time": {
"from": "08:30:00",
"to": "09:30:00"
}
}
]
}
}
my code
func onSynchronize(detailInfo: AppointmentDetail) {
let appointment = detailInfo
let fakeAddress = "fake address"
let fakeLocality = "Alderaan"
let store = EKEventStore()
store.requestAccess(to: .event) {(granted, error) in
if !granted { return }
let event = EKEvent(eventStore: store)
event.title = "my title"
guard let date0 = appointment.date else { return }
guard let hours = appointment.time else { return }
guard let host = appointment.host else { return }
if let componentsFrom = self.timeComponentsFromHourInString(from: hours.from) {
if let start = Calendar.current.date(byAdding: componentsFrom, to: date0, wrappingComponents: false) {
event.startDate = start
event.addAlarm(EKAlarm(absoluteDate: start.dayBefore))
event.addAlarm(EKAlarm(absoluteDate: start.halfHourBefore))
event.endDate = start.hourAfter
}
}
if let componentsTo = self.timeComponentsFromHourInString(from: hours.to) {
if let end = Calendar.current.date(byAdding: componentsTo, to: date0, wrappingComponents: false) {
event.endDate = end
}
}
event.location = fakeAddress.concats(fakeLocality, withSeparator: "-")
event.url = URL(string: BanksUtils.appLocalizeString(forKey: "url"))
if let managerDescription = host.managerDescription,
let manager = BanksUtils.localizeString(forKey: "handledBy").concats(managerDescription.capitalized),
let description = appointment.requestorDescription,
let reason = BanksUtils.localizeString(forKey: "reason").concats(description.capitalized) {
event.notes = manager + "\n" + reason
} else {
if let description = appointment.requestorDescription {
event.notes = BanksUtils.localizeString(forKey: "reason").concats(description.capitalized)
}
}
let structuredLocation = EKStructuredLocation(title: fakeAddress)
structuredLocation.geoLocation = self.location
event.structuredLocation = structuredLocation
event.calendar = store.defaultCalendarForNewEvents
do {
try store.save(event, span: .thisEvent, commit: true)
} catch {
Log.logger.error("Error: \(String(describing: error))")
}
guard let url = URL(string: "calshow:\(event.startDate.timeIntervalSinceReferenceDate)") else { return }
DispatchQueue.main.async {
UIApplication.shared.open(url, options: [:], completionHandler: nil)
}
}
}
///Allows to get HH:MM:SS from an hour in form of a string
func timeComponentsFromHourInString(from string: String) -> DateComponents? {
let comps = string.components(separatedBy: ":")
guard comps.count == 3,
let hr = Int(comps[0]),
let mn = Int(comps[1]),
let sc = Int(comps[2])
else { return nil }
return DateComponents(hour: hr, minute: mn, second: sc)
}
I want to create a date variable but get the following response:
_startDate Date <unavailable; try printing with "vo" or "po">
The code i have is:
func createMileagesPDF() {
var _someDate: NSDate = NSDate()
self.someDate = Date()
guard (!exportYear.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty && exportYear.count == 4) && cars.count > 0 else {
showAlert.toggle()
return
}
let _dateFormatter = DateFormatter()
//_dateFormatter.dateFormat = "dd-MM-yyyy"
let _startDateString = String(format: "01-01-%#", exportYear)
let _startDate = createdate() // = _dateFormatter.date(from: "01-12-2020 00:00:01")
let _x = createdate()
print("Create PDF")
}
func createdate() -> Date {
return Date()
}
What i want is an startdate based on an given year.
A string converted to an date.
When i do this in PlayGround it all works fine.
Thanks.
I am trying to get the difference between dates in days. I have a problem translating dates to the desired format.
func daysBefore(_ date: String) -> Int {
let currentDate = Date()
let dateFormater = DateFormatter()
dateFormater.dateFormat = "dd.mm.YYYY"
guard let nextDate = dateFormater.date(from: date) else {
return 0
}
return currentDate.interval(ofComponent: .day, fromDate: nextDate)
}
extension Date {
func interval(ofComponent comp: Calendar.Component, fromDate date: Date) -> Int {
let currentCalendar = Calendar.current
guard let start = currentCalendar.ordinality(of: comp, in: .era, for: date) else { return 0 }
guard let end = currentCalendar.ordinality(of: comp, in: .era, for: self) else { return 0 }
return end - start
}
}
daysBefore("22.09.2019")
When I convert the date from String to Date in:
let currentDate = Date()
let dateFormater = DateFormatter()
dateFormater.dateFormat = "dd.mm.YYYY"
guard let nextDate = dateFormater.date(from: date) else {
return 0
}
I always get something like: 2018-12-22 21:09:00 +0000.
But expected(in example): 22.09.2019.