I have a UIViewRepresentable of a third-party library component FSCalendar
. However, I need this to conform to type UIView... Is there a way to do this? Any help is appreciated :)
struct CalendarViewRepresentable: UIViewRepresentable {
typealias UIViewType = FSCalendar
var calendar = FSCalendar()
@Binding var selectedDate: Date
var calendarHeight: NSLayoutConstraint?
func updateUIView(_ uiView: FSCalendar, context: Context) { }
func makeUIView(context: Context) -> FSCalendar {
calendar.delegate = context.coordinator
calendar.dataSource = context.coordinator
calendar.translatesAutoresizingMaskIntoConstraints = false
calendar.setContentHuggingPriority(.required, for: .vertical)
calendar.setContentHuggingPriority(.required, for: .horizontal)
NSLayoutConstraint.activate([
calendar.topAnchor.constraint(equalTo: context.coordinator.topAnchor)
])
return calendar
}
func makeCoordinator() -> Coordinator {
Coordinator(self)
}
class Coordinator: NSObject, FSCalendarDelegate, FSCalendarDataSource {
var parent: CalendarViewRepresentable
init(_ parent: CalendarViewRepresentable) {
self.parent = parent
}
func calendar(_ calendar: FSCalendar, didSelect date: Date, at monthPosition: FSCalendarMonthPosition) {
parent.selectedDate = date
}
func calendar(_ calendar: FSCalendar, boundingRectWillChange bounds: CGRect, animated: Bool) {
parent.calendarHeight?.constant = bounds.height
parent.calendar.layoutIfNeeded()
}
}
}
struct HomeView: View {
@State private var selectedDate: Date = Date()
var body: some View {
VStack {
CalendarViewRepresentable(selectedDate: self.$selectedDate)
}
}
}
CodePudding user response:
We usually wrap a UIKit view (UIView) to be UIViewRepresentable whenever we want to use this view in a SwiftUI context. SwiftUI works with a view element called View.
On your case the UIKit view is FSCalendar, it's originally a UIView and wrapping it to be a UIViewRepresentable is helping us using it in a SwiftUI context as a SwiftUI View - therefore there is no reason to convert or make UIViewRepresentable to a UIView.
CodePudding user response:
Your implementation of UIRepresentable
with a Coordinator
isn't quite right, give this a try:
import SwiftUI
import FSCalendar
struct CalendarViewRepresentable: UIViewRepresentable {
@Binding var selectedDate: Date
func makeCoordinator() -> Coordinator {
Coordinator()
}
func makeUIView(context: Context) -> FSCalendar {
return context.coordinator.calendar
}
func updateUIView(_ uiView: FSCalendar, context: Context) {
uiView.select(selectedDate)
context.coordinator.didSelectDate = { date in
selectedDate = date
}
}
class Coordinator: NSObject, FSCalendarDelegate, FSCalendarDataSource {
lazy var calendar: FSCalendar = {
let calendar = FSCalendar()
calendar.delegate = self
calendar.dataSource = self
return calendar
}()
var didSelectDate: ((Date) -> ())?
func calendar(_ calendar: FSCalendar, didSelect date: Date, at monthPosition: FSCalendarMonthPosition) {
didSelectDate?(date)
}
}
}
struct FSCalendarTest: View {
@State private var selectedDate = Date()
var body: some View {
NavigationStack {
CalendarViewRepresentable(selectedDate: self.$selectedDate)
.navigationTitle("\(selectedDate, format: .dateTime)")
.toolbar {
Button("Now") {
selectedDate = Date()
}
}
}
}
}