Home > Software design >  How to make UIViewRepresentable inherit UIView?
How to make UIViewRepresentable inherit UIView?

Time:11-19

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()
                    }
                }
        }
    }
}

Screenshot

  • Related