Unable to push the Button placed next to Picker

66 Views Asked by At

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:

enter image description here

I tried using ZStack,and putting the button over the picker layer, but I could not solve it.

Xcode Version is 14.2.

0

There are 0 best solutions below