0

Newbie SwiftUI Dev here. I want to create a scheduling app in SwiftUI and I would like to create a button in navigation bar which change calendar's scope. From .week to month and return.

    struct HomeVC: View {
    
    init() {
        navbarcolor.configureWithOpaqueBackground()
        navbarcolor.backgroundColor = .systemGreen
        navbarcolor.titleTextAttributes = [.foregroundColor: UIColor.white]
        navbarcolor.largeTitleTextAttributes = [.foregroundColor: UIColor.white]
        UINavigationBar.appearance().standardAppearance = navbarcolor
        UINavigationBar.appearance().scrollEdgeAppearance = navbarcolor
       }
    
    @State private var selectedDate = Date()
    
var body: some View {
    NavigationView{
        VStack{
            CalendarRepresentable(selectedDate: $selectedDate)
                .frame(height: 300)
                .padding(.top, 15)
            
                Spacer()
           
                    ListView()
                }
            .navigationBarTitle("Calendar")
                .toolbar {
                    Button(action: {
                        switchCalendarScope()
                    }) {
                        Text("Toggle")
                    }
            }
        }
    }
}

This is my calendar struct, and I would like to take from here the switchCalendarScope function, and use it into button's action, but doesn't work.

struct CalendarRepresentable: UIViewRepresentable{
    typealias UIViewType = FSCalendar
    @Binding var selectedDate: Date
    var calendar = FSCalendar()
    
    func switchCalendarScope(){
        if calendar.scope == FSCalendarScope.month {
            calendar.scope = FSCalendarScope.week

        } else {
           calendar.scope = FSCalendarScope.month
        }

    }
    
    func updateUIView(_ uiView: FSCalendar, context: Context) { }
    
    func makeUIView(context: Context) -> FSCalendar {
        calendar.delegate = context.coordinator
        calendar.dataSource = context.coordinator
        calendar.allowsMultipleSelection = true
        calendar.scrollDirection = .vertical
        calendar.scope = .week
        
        //:Customization
        calendar.appearance.headerTitleFont =  UIFont.systemFont(ofSize: 25, weight: UIFont.Weight.heavy)
        calendar.appearance.weekdayFont = .boldSystemFont(ofSize: 15)
        calendar.appearance.weekdayTextColor = .black
        calendar.appearance.selectionColor = .systemGreen
        calendar.appearance.todayColor = .systemGreen
        calendar.appearance.caseOptions = [.headerUsesUpperCase, .weekdayUsesUpperCase]
        calendar.appearance.headerTitleColor = .black
        
        return calendar
    }
    
    func makeCoordinator() -> Coordinator {
        Coordinator(self)
    }
    
    class Coordinator: NSObject, FSCalendarDelegate, FSCalendarDataSource {
        var parent: CalendarRepresentable
        var formatter = DateFormatter()
        
        init(_ parent: CalendarRepresentable) {
            self.parent = parent
        }

        func calendar(_ calendar: FSCalendar, numberOfEventsFor date: Date) -> Int {
            return 0
        }
        
        func calendar(_ calendar: FSCalendar, didSelect date: Date, at monthPosition: FSCalendarMonthPosition) {
            formatter.dateFormat = "dd-MM-YYYY"
            print("Did select == \(formatter.string(from: date))")
        }
        
        func calendar(_ calendar: FSCalendar, didDeselect date: Date, at monthPosition: FSCalendarMonthPosition) {
            formatter.dateFormat = "dd-MM-YYYY"
            print("Did de-select == \(formatter.string(from: date))")
        }
    }
}

Can anybody help?

1 Answer 1

0

You don't need to trigger the function in your UIViewRepresentable. You simply need to declare a variable in there that is the representation of the selected scope, and pass that in with your initializer. I am going to assume that your scope variable is of Type Scope for this:

struct CalendarRepresentable: UIViewRepresentable {
    typealias UIViewType = FSCalendar
    @Binding var selectedDate: Date
    var calendar = FSCalendar()
    var scope: Scope
        
    func updateUIView(_ uiView: FSCalendar, context: Context) { }
    
    func makeUIView(context: Context) -> FSCalendar {
        calendar.delegate = context.coordinator
        calendar.dataSource = context.coordinator
        calendar.allowsMultipleSelection = true
        calendar.scrollDirection = .vertical

        // Set scope here
        calendar.scope = scope
        
        //:Customization

        ...

        return calendar
    }
...
}

Then from the HomeVC view you would call it like this:

        CalendarRepresentable(selectedDate: $selectedDate, scope: scope)

The view will get recreated as needed. Also, one last thing, in SwiftUI there are no ViewControllers. Your HomeVC should just be named Home. It is the view, not a view controller, and they work differently and take a different mental model. This is why you were struggling in solving this. Even the UIViewRepresentable is a view in the end, and it just wraps a ViewController and instantiates the view. And they are all structs; you don't mutate a struct, you simply recreate it when you need to change it.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.