Reputation: 93
I'm trying to build a calendar app for iOS using KVKCalendar but it's not originally build for Swift UI so I'm kind of struggling to achieve what I want to do.
My goal is changing calendar type (such as daily, weekly, monthly) by a segment controller, exactly like this example (which is already provided in git repository). sampleUI
So far, I managed to display daily style calendar view as default. But I don't know how I can change its calendar type from ContentView.swift
Does anyone know about this type of ViewController ↔ Swift UI thing?
My ContentView.swift is like this
import SwiftUI
import KVKCalendar
struct ContentView: View {
@State var events: [Event] = []
@State var selectedType: CalendarType = .week // I want this to change its calendar type.
var body: some View {
VStack{
CalendarDisplayView(events: $events)
}
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
And my ContentDisplayView.swift is like this
import SwiftUI
import EventKit
import KVKCalendar
struct CalendarDisplayView: UIViewRepresentable {
@Binding var events: [Event]
public init(events: Binding<[Event]>) {
self._events = events
}
private var calendar: CalendarView = {
var style = Style()
if UIDevice.current.userInterfaceIdiom == .phone {
style.timeline.widthTime = 40
style.timeline.currentLineHourWidth = 45
style.timeline.offsetTimeX = 2
style.timeline.offsetLineLeft = 2
style.headerScroll.titleDateAlignment = .center
style.headerScroll.isAnimateTitleDate = true
style.headerScroll.heightHeaderWeek = 70
style.event.isEnableVisualSelect = false
style.month.isHiddenTitle = true
style.month.weekDayAlignment = .center
} else {
style.timeline.widthEventViewer = 350
style.headerScroll.fontNameDay = .systemFont(ofSize: 17)
}
style.month.autoSelectionDateWhenScrolling = true
style.timeline.offsetTimeY = 25
style.startWeekDay = .monday
style.timeSystem = .current ?? .twelve
style.systemCalendars = ["Calendar"]
if #available(iOS 13.0, *) {
style.event.iconFile = UIImage(systemName: "paperclip")
}
style.locale = Locale.current
style.timezone = TimeZone.current
return CalendarView(frame: UIScreen.main.bounds, style: style)
}()
func makeUIView(context: UIViewRepresentableContext<CalendarDisplayView>) -> CalendarView {
calendar.dataSource = context.coordinator
calendar.delegate = context.coordinator
calendar.reloadData()
return calendar
}
func updateUIView(_ uiView: CalendarView, context: UIViewRepresentableContext<CalendarDisplayView>) {
context.coordinator.events = events
}
func makeCoordinator() -> CalendarDisplayView.Coordinator {
Coordinator(self)
}
class Coordinator: NSObject, CalendarDataSource, CalendarDelegate {
private let view: CalendarDisplayView
var events: [Event] = [] {
didSet {
view.calendar.reloadData()
}
}
init(_ view: CalendarDisplayView) {
self.view = view
super.init()
}
func eventsForCalendar(systemEvents: [EKEvent]) -> [Event] {
return events
}
}
}
Upvotes: 1
Views: 756
Reputation: 30318
First, add a @Binding
inside CalendarDisplayView
so it can update:
@Binding var selectedType: CalendarType
Then, pass in ContentView
's $selectedType
for CalendarDisplayView
's selectedType
, just like how you passed in $events
.
/// here!
CalendarDisplayView(events: $events, selectedType: $selectedType)
Finally, update the type inside updateUIView
, which is called whenever the @Binding
changes.
func updateUIView(_ uiView: CalendarView, context: UIViewRepresentableContext<CalendarDisplayView>) {
context.coordinator.events = events
calendar.set(type: selectedType, date: Date()) /// I've never used this library, so you might need to replace `Date()` with something else
calendar.reloadData()
}
Upvotes: 2