Reputation: 1
I'm creating a todo list with local notifications.
When I press the notification setting button on the right side of the two pickers , it does not work properly, and the selection display of the first picker appears.
import SwiftUI
import UserNotifications
struct ContentView: View {
@State var newItem: String = ""
@State var toDoList: [String] = []
@State var selectedValue1: [Int] = []
@State var selectedValue2: [Int] = []
var body: some View {
VStack {
//Register new to-do
HStack {
TextField("Please write a new task.", text: $newItem)
.textFieldStyle(RoundedBorderTextFieldStyle())
.frame(width: 300)
Button {
toDoList.append(newItem)
selectedValue1.append(-1)
selectedValue2.append(-1)
newItem = ""
UserDefaults.standard.set(toDoList, forKey: "ToDoList")
UserDefaults.standard.set(selectedValue1, forKey: "selectedValue1")
UserDefaults.standard.set(selectedValue2, forKey: "selectedValue2")
} label: {
ZStack {
RoundedRectangle(cornerRadius: 5)
.frame(width: 50, height: 30)
.foregroundColor(.green)
Text("Add").foregroundColor(.white)
}
}
}
//List of registered tasks
List {
ForEach(0 ..< toDoList.count) { index in
VStack{
HStack{
Text(toDoList[index])
Spacer()
}
todoDatePicker(index)
}
}
}
.id(UUID())
}
.onAppear() {
NotificationManager.instance.requestAutorization()
guard let defaultItem = UserDefaults.standard.array(forKey: "ToDoList") as? [String]
else { return }
guard let defaultSelectedValue1 = UserDefaults.standard.array(forKey: "selectedValue1") as? [Int]
else { return }
guard let defaultSelectedValue2 = UserDefaults.standard.array(forKey: "selectedValue2") as? [Int]
else { return }
toDoList = defaultItem
selectedValue1 = defaultSelectedValue1
selectedValue2 = defaultSelectedValue2
}
}
}
//Picker to set notification time
extension ContentView {
func todoDatePicker(_ index: Int) -> some View {
return HStack {
Text("Hour")
Picker("", selection: $selectedValue1[index]) {
ForEach(-1 ..< 24, id: \.self) { hour in
VStack{
if hour == -1 {
Text("--").tag(hour)
} else{
Text("\(hour)").tag(hour)
}
}
}
}
Text("Minute")
Picker("", selection: $selectedValue2[index]) {
ForEach(-1 ..< 60, id: \.self) { minute in
if minute == -1 {
Text("--").tag(minute)
} else {
Text("\(minute)").tag(minute)
}
}
}
Button {
NotificationManager.instance.scheduleNotification(todoSubtitle: toDoList[index], todoHour: selectedValue1[index], todoMinute: selectedValue2[index])
} label: {
Text("Set notification")
}
}
}
}
class NotificationManager {
static let instance = NotificationManager()
// Authorizing a notification
func requestAutorization() {
let options: UNAuthorizationOptions = [.alert, .sound, .badge]
UNUserNotificationCenter.current().requestAuthorization(options: options) { success, error in
if let error = error {
print("ERROR: \(error)")
} else {
print("SUCCESS")
}
}
}
// Local notification at set hour/minute
func scheduleNotification(todoSubtitle: String, todoHour: Int, todoMinute: Int) {
let content = UNMutableNotificationContent()
content.title = "Notification from To-do"
content.subtitle = todoSubtitle
content.sound = .default
content.badge = 1
var dateComponents = DateComponents()
dateComponents.hour = todoHour
dateComponents.minute = todoMinute
let trigger = UNCalendarNotificationTrigger(dateMatching: dateComponents, repeats: true)
let request = UNNotificationRequest(
identifier: UUID().uuidString,
content: content,
trigger: trigger)
UNUserNotificationCenter.current().add(request)
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
Preview of the App:
I tried using ZStack,and putting the button over the picker layer, but I could not solve it.
Xcode Version is 14.2.
Upvotes: 0
Views: 68