How can I specify some days to be available for reservation swiftui or UIKit - swift

How can I specify some days to be available for reservation in : swiftui , UIKit or if have any way in Firebase
this is Example:
day : 16,17,18,20 is available in
struct Test4: View {
let dateFormatter: DateFormatter = {
let formatter = DateFormatter()
formatter.dateStyle = .long
return formatter
}()
let dateFormatter2: DateFormatter = {
let formatter = DateFormatter()
formatter.dateFormat = "dd, MMMM, yyyy"
return formatter
}()
#State private var reservationDate = Date()
var body: some View {
VStack {
DatePicker("", selection: $reservationDate, in: Date()..., displayedComponents: .date)
.datePickerStyle(GraphicalDatePickerStyle())
Spacer()
Text("\(reservationDate, formatter: dateFormatter2)")
.font(.title)
.bold()
Spacer()
}
}
}

Related

Strings Dictionary with dynamic units

I would like to dynamically specify the unit to be used (e.g. hours, minutes, seconds) in the Strings Dictionary when called:
Text("\(unit) \(value))", tableName: "SingularAndPlural")
unit contains the unit as a string
value contains the value as an integer
But that doesn't work, it doesn't resolve.
I've tried all possible variants, but I can't get any further.
Rather than use stringsDict you should probably use localisation provided by the built-in Formatters. In this case DateComponentsFormatter probably does what you need:
struct ContentView: View {
var body: some View {
List {
ForEach(["en", "ru", "el", "th"], id: \.self) { localeId in
Section(localeId) {
ForEach(0..<3, id: \.self) { i in
HStack {
Text(formatter(localeId).string(from: DateComponents(minute: i))!)
Spacer()
Text(formatter(localeId).string(from: DateComponents(second: i))!)
}
}
}
}
}
}
func formatter(_ localeId: String) -> DateComponentsFormatter {
var calendar = Calendar.current
calendar.locale = Locale(identifier: localeId)
let formatter = DateComponentsFormatter()
formatter.calendar = calendar
formatter.unitsStyle = .full
return formatter
}
}
It's even simpler if you just want to format for the device's current locale:
struct ContentView: View {
var body: some View {
List {
ForEach(0..<3, id: \.self) { i in
HStack {
Text(DateComponents(minute: i), formatter: Self.formatter)
Spacer()
Text(DateComponents(second: i), formatter: Self.formatter)
}
}
}
}
static var formatter: DateComponentsFormatter {
let formatter = DateComponentsFormatter()
formatter.unitsStyle = .full
return formatter
}
}

How to change a string I get from API

I get a string with a date of the first flight for each of four rockets from this API. The string that I get looks like this: "2006-03-24". I want it to look this way: "24 March, 2006". I don't understand how to do this in SwiftUI.
My View with the dates:
struct DateView: View {
#State var rockets = [RocketInfo]()
var body: some View {
NavigationView {
if rockets.isEmpty {
ProgressView()
} else {
TabView {
ForEach(rockets) { rocket in
VStack {
HStack {
Text("First flight")
Spacer()
Text(rocket.firstFlight)
}
.padding()
}
}
}
.tabViewStyle(.page)
.navigationBarTitleDisplayMode(.inline)
.navigationBarHidden(true)
}
}
.onAppear {
InfoApi().getRockets { rockets in
self.rockets = rockets
}
}
}
}
struct DateView_Previews: PreviewProvider {
static var previews: some View {
DateView()
.preferredColorScheme(.dark)
}
}
Screenshot of the API data: enter image description here
The func gets a date from the string, which you then can format to your wishes.
var body: some View {
let dateString = "2006-03-24"
let date = dateFromString(dateString)
Text("\(date, style: .date)")
}
func dateFromString(_ string: String) -> Date {
let dateFormatter = DateFormatter()
dateFormatter.locale = .current
dateFormatter.dateFormat = "yyyy-MM-dd"
return dateFormatter.date(from: string) ?? Date()
}
You'll need two instances of DateFormatter - one to convert the string from API to a Date instance and the other to convert the date instance to your desired string format.
let dateFormatter1 = DateFormatter()
dateFormatter1.dateFormat = "yyyy-MM-dd" // Format of API Date
let dateFormatter2 = DateFormatter()
dateFormatter2.dateFormat = "d MMMM, yyyy" // Desired Format
let date = dateFormatter1.date(from: "2006-03-24")!
let desiredFormat = dateFormatter2.string(from: date)
print(desiredFormat) // prints "24 March, 2006"
First, I encourage you to change firstFlight in RocketInfo to be a Date object, to get the correct data representation in the model. You may have to configure your JSONDecoder to parse the date string correctly:
let decoder = JSONDecoder()
let formatter = DateFormatter()
formatter.dateFormat = "yyyy-MM-dd"
decoder.dateDecodingStrategy = .formatted(formatter)
Then, you need another DateFormatter when you want to convert that date back into a string:
let formatter = DateFormatter()
formatter.dateFormat = "d MMMM, yyyy"
let dateString = formatter.string(from: object.firstFlight)
Please see here for the list of custom formats supported by DateFormatter:
http://www.unicode.org/reports/tr35/tr35-31/tr35-dates.html#Date_Format_Patterns
(There's also a couple of system defined formats, please see dateStyle and timeStyle in the docs.)

Linking ObservableObject to DatePicker in SwiftUI

I am new to Swift and all its frameworks. I have a JSON file with readings for each day of the year. I have made a Decodable struct for the reading and an ObservableObject class which stores the readings in an array. I have made the ObservableObject an #EnvironmentObject so it can be accessed in all views. Can I link the readings to the date picker so that selecting a date will take me to a detailed view?
import SwiftUI
struct CalendarView: View {
// this is where ObserveableObject is required
#EnvironmentObject var days: Days
#State private var date = Date()
let dateFormatter: DateFormatter = {
let formatter = DateFormatter()
// formatter.dateStyle = .long
formatter.dateFormat = "LLLL d"
return formatter
}()
var body: some View {
VStack {
Text("Select a date to read")
.font(.largeTitle)
DatePicker("Select a date", selection: $date, displayedComponents: .date)
.datePickerStyle(GraphicalDatePickerStyle())
.labelsHidden()
.frame(maxHeight: 400)
Text("\(date, formatter: dateFormatter)")
}
.navigationTitle("Datepicker")
}
}
struct CalendarView_Previews: PreviewProvider {
static var previews: some View {
CalendarView()
}
}
//Replace this with your Decodable object
class Day : ObservableObject{
let id: UUID = UUID()
var date: Date
init( date: Date) {
self.date = date
}
}
class CalendarViewModel: ObservableObject, Identifiable {
#Published var days: [Day] = []
#Published var selectedDate: Date = Date()
var filteredDay: Day?{
days.filter({
Calendar.current.isDate($0.date, equalTo: selectedDate, toGranularity: .day)
}).first
}
init() {
//Create sample Days you can remove this and populate your array with acual data
for n in 1...30{
days.append(Day(date: Date().addingTimeInterval(TimeInterval(60*60*24*n))))
days.append(Day(date: Date().addingTimeInterval(TimeInterval(-60*60*24*n))))
}
}
}
struct CalendarView: View {
#StateObject var vm: CalendarViewModel = CalendarViewModel()
#State var isVisible: Bool = false
let dateFormatter: DateFormatter = {
let formatter = DateFormatter()
// formatter.dateStyle = .long
formatter.dateFormat = "LLLL d"
return formatter
}()
var body: some View {
NavigationView{
ScrollView {
Text("Select a date to read")
.font(.largeTitle)
DatePicker("Select a date", selection: $vm.selectedDate, displayedComponents: .date)
.datePickerStyle(GraphicalDatePickerStyle())
.labelsHidden()
.frame(maxHeight: 400)
Text("\(vm.selectedDate, formatter: dateFormatter)")
if vm.filteredDay != nil{
NavigationLink(
destination: DayView(day: vm.filteredDay!),
isActive: $isVisible,
label: {
Text("View Day")
})
}else{
Text("No results for selected day")
}
}
.navigationTitle("Datepicker")
}
}
}
struct DayView:View {
//Observe the actual Day here for changes
#ObservedObject var day: Day
let dateFormatter: DateFormatter = {
let formatter = DateFormatter()
// formatter.dateStyle = .long
formatter.dateFormat = "LLLL d"
return formatter
}()
var body: some View {
VStack{
Text(dateFormatter.string(from: day.date))
}
}
}

How can I initialize SwiftUI DatePicker .hourAndMinute element?

I am trying to initialize this "WakeUpDate" date element so that the default displayed value is 10:00 AM. This date picker is HourandMinute only and is being stored in userdefaults.
I tried to init the date element but it is not building. With this error: Cannot assign value of type 'State<Date>' to type 'Published<Date>'
UserData: Currently, the following init does not build
import Foundation
import SwiftUI
class UserData: ObservableObject {
init() {
_wakeUpTime = State<Date>(initialValue: Calendar.current.date(DateComponents(Hour: 10)) ?? Date())
}
#Published var wakeUpTime: Date = UserDefaults.standard.object(forKey: "wakeUpTime") as? Date ?? Date() {
didSet {
UserDefaults.standard.set(self.wakeUpTime, forKey: "wakeUpTime")
}
}
}
SettingsDetail: Where the DatePicker is being selected:
struct SettingsDetailView: View {
#ObservedObject var userData: UserData
var body: some View {
Form{
DatePicker("Select a new time", selection: $userData.wakeUpTime, displayedComponents: .hourAndMinute)
}
}
}
MainSettings: Where the selected DatePicker Date is being displayed:
import SwiftUI
import UserNotifications
struct SettingsView: View {
#ObservedObject var userData = UserData()
static var dateFormatter: DateFormatter = {
let formatter = DateFormatter()
formatter.dateFormat = "hh:mm a"
return formatter
}()
var body: some View {
NavigationView {
VStack (alignment: .center, spacing: 0) {
Form{
Section(header: Text("NOTIFICATION SETTINGS")) {
HStack {
Text("Current Notification Time")
.foregroundColor(Color("MainText"))
Spacer()
Text("\(self.userData.wakeUpTime, formatter: SettingsView.self.dateFormatter)")
}
}
}
}
}
}
}
EDIT I tried initializing UserData like this, but now when I pick a new time with the date picker and quit the app, the new time is gone and 5PM (the init time) is displayed again.
import Foundation
import SwiftUI
class UserData: ObservableObject {
init() {
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "HH:mm"
if let date = dateFormatter.date(from:"17:00") {
wakeUpTime = date
}
}
#Published var wakeUpTime: Date = UserDefaults.standard.object(forKey: "wakeUpTime") as? Date ?? Date() {
didSet {
UserDefaults.standard.set(self.wakeUpTime, forKey: "wakeUpTime")
}
}
}
How can I run init only on the first launch, and be removed once the selected time has been picked with the datepicker?
I figured it out by doing this:
class UserData: ObservableObject {
#AppStorage("userdatahaslaunched") var userdatahaslaunched = false
init() {
if !userdatahaslaunched {
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "HH:mm"
if let date = dateFormatter.date(from:"10:00") {
wakeUpTime = date
}
userdatahaslaunched = true
}
}
If your intent is to let the user initialize a wake up time you should always expect a date after now. So what you are looking for is calendar method nextDate(after:) and you can match the desired components (hour and minute). Note that you don't need to include the minutes component when calling this method if it is zero.
let date = Calendar.current.nextDate(after: Date(), matching: .init(hour: 10), matchingPolicy: .strict)!
print(date.description(with: .current))

Date to String => Time is missing

I am trying to convert date to string so I can save this data in firestore. But my getDate func is getting only today's date, not the time
struct NewTaskView: View {
#State var taskTitle = ""
#State var taskFrom = ""
#State var taskFromDate = Date()
var body: some View {
NavigationView {
VStack(alignment: .leading) {
Group { // Type '()' cannot conform to 'View'; only struct/enum/class types can conform to protocols
Text("Task Title")
TextField("Title", text:$taskTitle )
Divider()
Text("From")
DatePicker("", selection: $taskFromDate, in: Date()...)
.labelsHidden()
.onReceive(Just(taskFromDate)) { data in
taskFrom = getDate(date: taskFromDate)
}
Divider()
} .padding(.horizontal, 10)
.font(Font.custom("SFCompactDisplay-Bold", size: 25))
.foregroundColor(.gray)
func getDate(date: Date) -> String {
let formatter = DateFormatter()
formatter.dateStyle = .full
let dateTime = formatter.string(from: date)
return dateTime
}
func getDate(date: Date) -> String {
let formatter = DateFormatter()
formatter.dateStyle = .full
formatter.timeStyle = .short
let dateTime = formatter.string(from: date)
return dateTime
}
You can use the following function:
func getDate(date:Date) -> String{
let formatter = DateFormatter()
formatter.locale = Locale(identifier: "en_US_POSIX")
formatter.timeZone = TimeZone(secondsFromGMT: 0)
formatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSSZZZZZ"
let updatedAtStr = "2016-06-05T16:56:57.019+01:00"
let updatedAt = formatter.date(from: updatedAtStr)
let result = "\(updatedAt!)".split(separator: " ")
return String(result[0]+" "+result[1])
}