Search code examples
swiftuiuikit

how to pass FSCalendar data from UIKIT to SwiftUI


I am a designer and try to develop a to-do list app. In the app, user select one day in calendar, it will to shows to-do list of selected day. But how can i pass selected date from FSCalendar(UIKIT) to to-do list(SwiftUI)?

Thanks so much!

My app demo in github: https://github.com/ElvishR/FSCalendar-To-Do-List-Test.git

Content View:

import SwiftUI
import Foundation

class UserData: ObservableObject{
    @Published var name = "Helsdfsflo"
}


struct ContentView: View {
    @ObservedObject var userData = UserData()
    var body: some View {
        
        Text(userData.name)
        Button(action:{
            print(self.userData.name)
        }){
            Text(" click to show the selected date")
        }
        CalendarModuleView()
            .frame(width: .infinity, height: 300.0, alignment: .center)
    }
}

Calendar View

import SwiftUI
import FSCalendar

class CalendarModule: UIViewController, FSCalendarDelegate {
    
    var calendar = FSCalendar()
    var formatter = DateFormatter()
    var SelectedDate = ""
    
    let integration = UserData()
    


    fileprivate lazy var dateFormatter: DateFormatter = {
        let formatter = DateFormatter()
        formatter.dateFormat = "yyyy/MM/dd"
        return formatter
    }()
    
    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: 300.0)
        calendar.appearance.todayColor = UIColor.systemGreen   
        calendar.appearance.selectionColor = UIColor.systemBlue
    }
    
    //selected day
        func calendar(_ calendar: FSCalendar, didSelect date: Date, at monthPosition: FSCalendarMonthPosition){
       // Do the same inside this function and you should be fine
        formatter.dateFormat = "yyyy-MM-dd"
        SelectedDate = formatter.string(from: date)
        ContentView().userData.name = formatter.string(from: date)
        print(ContentView().userData.name)
        print("calendar did select date \(self.formatter.string(from: date))")
        
      
    }
    
    func calendar(calendar: FSCalendar!, didSelectDate date: NSDate!) {
        formatter.dateFormat = "yyyy-MM-dd"
        SelectedDate = formatter.string(from: date as Date)
        print("(self.formatter.string(from: date))")
    }
   
}

APP Screenshot enter image description here


Solution

  • Use the UIViewRepresentable protocol for bind UIView class with SwiftUI. Here is a demo:

    struct CalendarModuleView: UIViewRepresentable {
        
        @Binding var selectedDate: Date?
        
        func makeCoordinator() -> Coordinator {
            Coordinator(self)
        }
        
        func makeUIView(context: Context) -> FSCalendar {
            let calendar = FSCalendar()
            calendar.delegate = context.coordinator
            calendar.appearance.todayColor = UIColor.systemGreen
            calendar.appearance.selectionColor = UIColor.systemBlue
            return calendar
        }
        
        func updateUIView(_ uiView: FSCalendar, context: Context) {
            
        }
        
        class Coordinator: NSObject, FSCalendarDelegate {
            
            var parent: CalendarModuleView
            
            init(_ calender: CalendarModuleView) {
                self.parent = calender
            }
            
            func calendar(_ calendar: FSCalendar, didSelect date: Date, at monthPosition: FSCalendarMonthPosition) {
                self.parent.selectedDate = date
            }
        }
    }
    

    Your ContentView

    class UserData: ObservableObject{
        @Published var name = "Helsdfsflo"
        @Published var date: Date?
    }
    
    
    struct ContentView: View {
        
        @ObservedObject private var userData = UserData()
        
        static let taskDateFormat: DateFormatter = {
            let formatter = DateFormatter()
            formatter.dateFormat = "yyyy-MM-dd"
            return formatter
        }()
        
        var body: some View {
            
            Text(userData.name)
            if userData.date != nil {
                Text("Task due date: \(userData.date!, formatter: Self.taskDateFormat)")
            }
            
            Button(action:{
                print(self.userData.name)
            }){
                Text(" click to show the selected date")
            }
            CalendarModuleView(selectedDate: $userData.date)
                .frame(height: 300.0, alignment: .center)
        }
    }