3

I'm currently trying to add a calendar interface in my app where when you click on a day at the bottom it will show details about events on that day. Currently I am using FSCalendar as my calendar.

I realised that this library is for UIKit and I would have to wrap it with representable protocol to get it working in SwiftUI.

I've been watching youtube and looking up guides on integrating UIKit in SwiftUI to help me do this. This is what I have currently:

import SwiftUI
import FSCalendar

CalendarModule.swift:
class CalendarModule: UIViewController, FSCalendarDelegate {
    
    var calendar = FSCalendar()
    
    override func viewDidLoad() {
        super.viewDidLoad()
        calendar.delegate = self
    }
    
    override func viewDidLayoutSubviews() {
        super.viewDidLayoutSubviews()
        initCalendar()
        view.addSubview(calendar)
    }
    
    private func initCalendar() {
        calendar.frame = CGRect(x: 0, y: 0, width: view.frame.size.width, height: view.frame.size.width)
        calendar.appearance.todayColor = UIColor.systemGreen
        calendar.appearance.selectionColor = UIColor.systemBlue
    }
}

struct CalendarModuleViewController: UIViewControllerRepresentable {
    
    typealias UIViewControllerType = UIViewController
    
    func makeUIViewController(context: UIViewControllerRepresentableContext<CalendarModuleViewController>) -> UIViewController {
        let viewController = CalendarModule()
        return viewController
    }
    
    func updateUIViewController(_ uiViewController: UIViewController, context: UIViewControllerRepresentableContext<CalendarModuleViewController>) {
    
    }
    
    func makeCoordinator() -> Coordinator {
        return Coordinator(self)
    }
    
    final class Coordinator: NSObject, FSCalendarDelegate {
        private var parent: CalendarModuleViewController
        
        
        init (_ parent: CalendarModuleViewController) {
            self.parent = parent
        }
        
    }
}

struct CalendarModuleView: View {
    
    var body: some View {
        CalendarModuleViewController()
    }
    
}

CalendarView.swift - Displaying calendar in top half and the details in bottom half:

import SwiftUI

struct CalendarView: View {
    var body: some View {
        NavigationView {
            VStack{
                VStack {
                    Spacer()
                    CalendarModuleView()
                    Spacer()
                }
                VStack {
                    Spacer()
                    Text("Details")
                    Spacer()
                }
            }.navigationBarTitle(Text("Calendar"), displayMode: .inline)
                .navigationBarItems(trailing:
                    NavigationLink(destination: CreateEventView().environmentObject(Event())) {
                        Image(systemName: "plus").imageScale(.large)
                    }.buttonStyle(DefaultButtonStyle())
            )
        }
    }
}

struct CalendarView_Previews: PreviewProvider {
    static var previews: some View {
        CalendarView()
    }
}

ContentView - Just displaying my CalendarView:

import SwiftUI

struct ContentView: View {

    var body: some View {
        CalendarView()
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}

The calendar looks like this so far:

Image of Calendar view

The calendar module itself works but I got stuck in writing the Coordinator to handle the delegates. Specifically the didSelectDate one..

When I start typing didSelectDate in the Coordinator class and look through the suggestions I only get

func calendar(_ calendar: FSCalendar, didSelect date: Date, at monthPosition: FSCalendarMonthPosition) {
    <#code#>
}

Am I wrapping the view controller wrong? Or should I be making my own UIView and UIViewController for FSCalendar then create UIViewRepresentable and UIViewControllerRepresentable to use in SwiftUI?

Ted Lim
  • 67
  • 7
  • The one you mentioned and willSelect are the only ones available in the library for the mentioned search. So whats the problem? Which delegate are you looking for? For reference you can look in FSCalendar.h which explains each delegate. – m.umar Sep 01 '20 at 09:24
  • This can be customisable as you want -> https://github.com/yodagamaheshan/DateGrid – YodagamaHeshan Oct 28 '20 at 06:01

1 Answers1

0

This is an old question, but still.

I think the problem is that you assign CalendarModule as a delegate and not the Coordinator

you need to write the following code:

func makeUIViewController(context: UIViewControllerRepresentableContext<CalendarModuleViewController>) -> UIViewController {
    let viewController = CalendarModule()
    viewController.calendar.delegate = context.coordinator // ->> Add this
    return viewController
}

After that, you should be able to implement delegate methods in the Coordinator

Evgeny Mitko
  • 245
  • 2
  • 12