- December 17, 2024
- Mins Read
KVKCalendar is a most fully customization calendar. Library consists of five modules for displaying various types of calendar (day, week, month, year, list of events). You can choose any module or use all. It is designed based on a standard iOS calendar, but with additional features. Timeline displays the schedule for the day and the week.
Additional features:
If you have a question about how to use KVKCalendar in your application, ask it on StackOverflow using the KVKCalendar tag.
Please, use Issues only for reporting bugs or requesting a new features in the library.
KVKCalendar is available through CocoaPods or Carthage or Swift Package Manager.
pod ‘KVKCalendar’
Adding Pods to an Xcode project
github “kvyatkovskys/KVKCalendar”
Adding Frameworks to an Xcode project
https://github.com/kvyatkovskys/KVKCalendar.git
) and click Next.Adding Package Dependencies to Your App
Import KVKCalendar
. Create a subclass view CalendarView
and implement CalendarDataSource
protocol. Create an array of class [Event]
and return the array.
import KVKCalendar
class ViewController: UIViewController {
var events = [Event]()
override func viewDidLoad() {
super.viewDidLoad()
let calendar = CalendarView(frame: frame)
calendar.dataSource = self
view.addSubview(calendar)
createEvents { (events) in
self.events = events
self.calendarView.reloadData()
}
}
override func viewWillLayoutSubviews() {
super.viewWillLayoutSubviews()
// to track changing frame when an user rotates device
calendarView.reloadFrame(view.frame)
}
}
extension ViewController {
func createEvents(completion: ([Event]) -> Void) {
let models = // Get events from storage / API
let events = models.compactMap({ (item) in
var event = Event(ID: item.id)
event.start = item.startDate // start date event
event.end = item.endDate // end date event
event.color = item.color
event.isAllDay = item.allDay
event.isContainsFile = !item.files.isEmpty
event.recurringType = // recurring event type – .everyDay, .everyWeek
// Add text event (title, info, location, time)
if item.allDay {
event.text = “\(item.title)”
} else {
event.text = “\(startTime) – \(endTime)\n\(item.title)”
}
return event
})
completion(events)
}
}
extension ViewController: CalendarDataSource {
func eventsForCalendar(systemEvents: [EKEvent]) -> [Event] {
// if you want to get events from iOS calendars
// set calendar names to style.systemCalendars = [“Test”]
let mappedEvents = systemEvents.compactMap { Event(event: $0) }
return events + mappedEvents
}
}
Implement CalendarDelegate
to handle user action and control calendar behaviour.
calendar.delegate = self
To use a custom view for specific event or date you need to create a new view of class EventViewGeneral
and return the view in function.
class CustomViewEvent: EventViewGeneral {
override init(style: Style, event: Event, frame: CGRect) {
super.init(style: style, event: event, frame: frame)
}
}
// an optional function from CalendarDataSource
func willDisplayEventView(_ event: Event, frame: CGRect, date: Date?) -> EventViewGeneral? {
guard event.ID == id else { return nil }
return customEventView
}
To use a custom date cell, just subscribe on this optional method from CalendarDataSource
(works for Day/Week/Month/Year views).
func dequeueCell<T>(parameter: CellParameter, type: CalendarType, view: T, indexPath: IndexPath) -> KVKCalendarCellProtocol? where T: UIScrollView {
switch type {
case .year:
let cell = (view as? UICollectionView)?.dequeueCell(indexPath: indexPath) { (cell: CustomYearCell) in
// configure the cell
}
return cell
case .day, .week, .month:
let cell = (view as? UICollectionView)?.dequeueCell(indexPath: indexPath) { (cell: CustomDayCell) in
// configure the cell
}
return cell
case .list:
let cell = (view as? UITableView)?.dequeueCell { (cell: CustomListCell) in
// configure the cell
}
return cell
}
}
Add a new SwiftUI
file and import KVKCalendar
. Create a struct CalendarViewDisplayable
and declare the protocol UIViewRepresentable
for connection UIKit
with SwiftUI
.
import SwiftUI
import KVKCalendar
struct CalendarViewDisplayable: UIViewRepresentable {
@Binding var events: [Event]
var selectDate = Date()
var style = Style()
private var calendar = KVKalendarView(frame: .zero)
func makeUIView(context: UIViewRepresentableContext<CalendarViewDisplayable>) -> KVKCalendarView {
calendar.dataSource = context.coordinator
calendar.delegate = context.coordinator
return calendar
}
func updateUIView(_ uiView: KVKCalendarView, context: UIViewRepresentableContext<CalendarViewDisplayable>) {
context.coordinator.events = events
}
func makeCoordinator() -> CalendarDisplayView.Coordinator {
Coordinator(self)
}
public init(events: Binding<[Event]>) {
_events = events
calendar = KVKCalendarView(frame: frame, date: selectDate, style: style)
}
// MARK: Calendar DataSource and Delegate
class Coordinator: NSObject, CalendarDataSource, CalendarDelegate {
private let view: CalendarViewDisplayable
var events: [Event] = [] {
didSet {
view.events = events
view.calendar.reloadData()
}
}
init(_ view: CalendarViewDisplayable) {
self.view = view
super.init()
}
func eventsForCalendar(systemEvents: [EKEvent]) -> [Event] {
events
}
}
}
Create a new SwiftUI
file and add CalendarViewDisplayable
to body
.
import SwiftUI
struct CalendarContentView: View {
@State var events: [Event] = []
var body: some View {
NavigationStack {
CalendarViewDisplayable(events: $events)
}
}
}
To customize calendar create an object Style
and add to init
class CalendarView
.
public struct Style {
public var event = EventStyle()
public var timeline = TimelineStyle()
public var week = WeekStyle()
public var allDay = AllDayStyle()
public var headerScroll = HeaderScrollStyle()
public var month = MonthStyle()
public var year = YearStyle()
public var list = ListViewStyle()
public var locale = Locale.current
public var calendar = Calendar.current
public var timezone = TimeZone.current
public var defaultType: CalendarType?
public var timeHourSystem: TimeHourSystem = .twentyFourHour
public var startWeekDay: StartDayType = .monday
public var followInSystemTheme: Bool = false
public var systemCalendars: Set<String> = []
}
A vertical stackview which takes subviews with different widths and adds them to it's rows with paddings, spacings etc.
AudioManager is a Swift package that provides a modular and easy-to-use interface for implementing audio feedback in your applications. It ...