swiftUI : How I can add Daily tasks by using DatePicker to CalendarView - date

import Foundation
import SwiftUI
struct Task : Identifiable {
let id = UUID()
let title : String
let scheduledTime : Date = Date()
let duration : Int? = nil
}
struct TaskTimeModel : Identifiable {
let id = UUID()
let task : [Task]
let taskDate : Date
}
func getTaskDate(offset: Int) -> Date {
let calendar = Calendar.current
let date = calendar.date(byAdding: .day, value: offset, to: Date())
return date ?? Date()
}
var tasksDemo : [TaskTimeModel] = [
TaskTimeModel(task: [Task(title: "경윤 약속"), Task(title: "아키 약속")], taskDate: getTaskDate(offset: 1)),
TaskTimeModel(task: [Task(title: "영희 약속"), Task(title: "철수 약속")], taskDate: getTaskDate(offset: 2)),
]
Hi! The codes above are about my task model related with Date
As you can see my attached picture, the task's date will be used to show when it the task in Calendar date.
I want to know is that If I want to add task by using datePicker,
How I can add the task with what dateformat or function.
I used getTaskDate function to use demo model on my Calendar, but by that, I can make the tasks using offset option only.
Please help me!
p.s My point is if I want to add task in 3th April, I want to add this date to task right away!, not using offset!

Related

How to handle multiple queries of different HKQuantityTypeIdentifier

I'm trying to get multiple types of health data all with the same timeframe. My problem relies on the way that I should handle all the data that I get from those queries. Currently my model is as follows:
struct DailyData {
var steps: Int?
var distance: Int?
var calories: Int?
var exercise: Int?
}
class UserData {
let healthManager = HealthKitManager.shared
var dailyData = [DailyData]?
.
.
.
}
if I'm not mistaken, I can only query only one HKQuantityIdentifier at a time, so that means I need to call my getData() function from my HealthKitManager.swift once for every HKQuantityType that I have in my model:
func getData(type: HKQuantityTypeIdentifier, unit: HKUnit, days: Int, completed: #escaping (Result<[Int], Error>) -> Void) {
let calendar = NSCalendar.current
let interval = NSDateComponents()
interval.day = 1
let quantityType = HKQuantityType.quantityType(forIdentifier: type)!
var anchorComponents = calendar.dateComponents([.day, .month, .year], from: NSDate() as Date)
anchorComponents.hour = 0
let anchorDate = calendar.date(from: anchorComponents)
// Define 1-day intervals starting from 0:00
let query = HKStatisticsCollectionQuery(quantityType: quantityType,
quantitySamplePredicate: nil,
options: .cumulativeSum,
anchorDate: anchorDate!,
intervalComponents: interval as DateComponents)
query.initialResultsHandler = {query, results, error in
if let error = error {
completed(.failure(error))
return
}
let endDate = NSDate()
let startDate = calendar.date(byAdding: .day, value: -(days - 1), to: endDate as Date, wrappingComponents: false)
var completeDataArray: [Int] = []
if let myResults = results{
myResults.enumerateStatistics(from: startDate!, to: endDate as Date) { statistics, stop in
if let quantity = statistics.sumQuantity(){
let dayData = quantity.doubleValue(for: unit)
completeDataArray.append(Int(dayData))
}
}
}
completed(.success(completeDataArray))
}
healthStore.execute(query)
}
My problem is that I can't find a way to correctly set the received data into my model. Could someone point me in the right direction? I believe my model could be wrong, because as for what I have gather online, it's impossible to query multiple HKQuantityTypes in one query. Meaning that I would definitely have to set my model one [Int] of a HKtype at a time.
But with what I currently have, that would mean that when the first query returns I have to create multiple DailyData objects with almost all of the variables nil except the one I'm setting. Then, when the other queries return, I should do some array checking of dailyData matching the .count values with the one I got from the query, and that just feels wrong in my opinion. Not very elegant.
I tried another approach. Instead of having an array of a custom type, having a custom type that inside has an array of ints for every HKType that I need. But this has another problem: How could I "Keep in sync" the data from every HKType? having different arrays for every type would be, in my opinion, difficult to handle for example in a tableView. How could I set number of rows in section? Which type should I prefer? Also I would be accessing data over array indexes which may lead to bugs difficult to solve.
struct WeekData {
var steps: [Int]?
var distance: [Int]?
var calories: [Int]?
var exercise: [Int]?
}
class UserData {
let healthManager = HealthKitManager.shared
var weekData = WeekData()
.
.
.
}

I have a database, if I want to retrieve a field of a specific document I can, but I would like to retrieve a field from the last document updated

In this way it works, I go to retrieve the field of that document (in this case the extranote), but what if I would only be interested in that field of the last document inserted chronologically?
I looked for similar examples but I wouldn't want just a few options, which I obviously don't know, to add when I create the db.
This model was created to read directly into the database without going through the App:
struct WorkoutModel: Identifiable,Codable {
//var id = UUID().uuidString
#DocumentID var id : String?
var extranote : String
var error: String = ""
}
struct SimpleEntry: TimelineEntry {
let date: Date
var deviceCount: Int
var deviceMake: String
var deviceModel: String
var deviceType: String
let configuration: ConfigurationIntent
var workoutData: WorkoutModel?
}
func fetchFromDB(completion: #escaping (WorkoutModel)->()){
let db = Firestore.firestore().collection("devices").document("lEp5impGTGeBmAEisQT")
db.getDocument { snap, err in
guard let doc = snap?.data() else {
completion(WorkoutModel(extranote: "", error: err?.localizedDescription ?? ""))
return
}
let extranote = doc["extranote"] as? String ?? ""
completion(WorkoutModel(extranote: extranote))
}
}
func getTimeline(for configuration: ConfigurationIntent, in context: Context,
completion: #escaping (Timeline<Entry>) -> ()) {
var entries: [SimpleEntry] = []
// Generate a timeline consisting of five entries an hour apart, starting
from the current date.
let date = Date()
let nextUpdate = Calendar.current.date(byAdding: .minute, value: 5, to:date)!
fetchFromDB { work in
let entry = SimpleEntry(date: nextUpdate, deviceCount:
deviceCount,deviceMake: deviceMake,deviceModel: deviceModel,deviceType:
deviceType, configuration: configuration, workoutData: work)
entries.append(entry)
let timeline = Timeline(entries: entries, policy: .atEnd)
completion(timeline)
}
}
If you don't know the ID of the document to update, then you will need to query the collection for the document. If you don't have a field in that document that indicates the timestamp of its last update, then you won't be able to make that query at all. So, you will have to add a field to the document, and make sure it's populated with the current timestamp every time you write it. Then you can use that field to make the query if you want to update it again later.

How do I fetch a date range of a week to extract from core data?

How do I query a date range in Swift code data IOS? If I store attributes: date, breakfast meals, lunch meals. How can I query what meals I ate this week?
I was able to get the current week using the following code:
var today = Date()
//finds date for Sunday start of week
var todayweekdaycomp = Calendar.component(.weekday, from: Date())
let startOfWeekSunday = Calendar.current.date(byAdding: .day, value: -(todayweekdaycomp - 1), to: today)!
//finds date for Saturday end of week
let endOfWeekSatvalue = 7 - todayweekdaycomp
let endofWeekSat = Calendar.current.date(byAdding: .day, value: endOfWeekSatvalue, to: today)!
//array of dates this week
var arr: [Date] = []
for n in 1...7 {
arr.append(Calendar.current.date(byAdding: .day, value: n, to: startOfWeekSunday)!)
}
Defining the begin date :
First you have to define a begin date. This will help us retrieve all the meals from that date .
If you want to get it from 7 days ago define it like that :
let calendar = Calendar.current
let beginDate = calendar.date(byAdding: .day, value: -7, to: Date())!
If you want to get it since the beginning of the week you first need to add this extension :
extension Date {
func startOfWeek(using calendar: Calendar = Calendar(identifier: .gregorian)) -> Date {
calendar.dateComponents([.calendar, .yearForWeekOfYear, .weekOfYear], from: self).date!
}
}
Then you can define your begin date like so :
let beginDate = Date().startOfWeek()
Creating the request :
// Creating the predicate.
let predicate = NSPredicate(format: "%K >= %#", #keyPath(YourData.date) ,beginDate as NSDate)
let request: NSFetchRequest<YourData> = YourData.fetchRequest()
// Adding a predicate to your request.
request.predicate = predicate
Note that you need to replace "YourData" by the name of the class of your meal data object.
Once you have your request ready you can fetch it as usual.

Cannot convert value of type 'Date' to expected argument type 'Date'

In playgrounds this code works great and I get the expected output exactly as I want, but when I go put it in my Xcode project I get 3 warning with my startDate saying
Cannot convert value of type 'Date' to expected argument type 'Date'
Here is my code:
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "MMMM, dd yyyy"
let date = dateFormatter.date(from: "June, 27 2018")
if let date = date {
let calendar = Calendar(identifier: .gregorian)
var startDate : Date = Date()
var interval : TimeInterval = 0
if calendar.dateInterval(of: .weekOfYear, start: &startDate, interval: &interval, for: date) {
print(startDate)
let daysToAdd = 6
var dateComponent = DateComponents()
dateComponent.day = daysToAdd
let futureDate = Calendar.current.date(byAdding: dateComponent, to: startDate)
let dateFormatter1 = DateFormatter()
dateFormatter1.dateFormat = "MMMM dd-"
let dateFormatter2 = DateFormatter()
let startWeek = dateFormatter1.string(from: startDate)
dateFormatter2.dateFormat = "dd"
let endWeek = dateFormatter2.string(from: futureDate!)
results = "\(startWeek)\(endWeek)"
}
}
The green text color on Date type in
var startDate : Date = Date()
means that you have your own class/struct that is called Date. That one cannot be converted to Foundation.Date.
It's not a good idea to create this kind of name conflict in the first place but you can fix it just using the full name:
var startDate = Foundation.Date()
var startDate = Date()
I had the same issue and I fixed that with the code above. hope works for you.
To illustrate this issue with an example.
This will produce the error, because while I did want to return a Date in the Result object, I didn't need to create a generic called Date at the interface for this function. That was my mistake.
func daysAgo<Date>(_ dayCount: Int) -> Result<Date, CommonErrors> {
let date: Date? = Calendar.current.date(byAdding: .day, value: dayCount, to: self)
return Result(success: date, failure: .initFailed)
}
The following code solves my issue:
func daysAgo(_ dayCount: Int) -> Result<Date, CommonErrors> {
let date: Date? = Calendar.current.date(byAdding: .day, value: dayCount, to: self)
return Result(success: date, failure: .initFailed)
}

How do I filter events created for the current date in the Realm swift?

How do I filter events created for the current date in the Realm swift?
I tried something like below but this wrong.
let dtSource = datasource.filter("Create == NSDate()").count
Update: Getting the filter creating my date as a string.
http://i.stack.imgur.com/8fLX9.png
http://i.stack.imgur.com/HDR2X.png
A query in the form of Create == NSDate() will check exact date equality, which will compare down to the second. If you want to check if a date is between a given interval, like checking if it's on a specific day, regardless of the time of day, you could do a BETWEEN check:
let dtSource = datasource.filter("Create BETWEEN %#", [firstDate, secondDate]).count
Update:
Here's a full code sample to get all date models for the current day:
import RealmSwift
class Event: Object {
dynamic var date = NSDate()
}
let todayStart = Calendar.current.startOfDay(for: Date())
let todayEnd: Date = {
let components = DateComponents(day: 1, second: -1)
return Calendar.current.date(byAdding: components, to: todayStart)!
}()
events = realm.objects(Event.self).filter("date BETWEEN %#", [todayStart, todayEnd])