Need help with KVKCalendar?
Click the “chat” button below for chat support from the developer who created it, or find similar developers for support.

About the developer

kvyatkovskys
230 Stars 65 Forks MIT License 576 Commits 11 Opened issues

Description

A most fully customization calendar and timeline library for iOS 📅

Services available

!
?

Need anything else?

Contributors list

CI Status Version Carthage SwiftPM compatible Platform License

KVKCalendar

KVKCalendar is a most fully customization calendar and timeline library. 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 week.

Additional features: - [x] Dark mode - [ ] Skeleton loading - [x] Custom event view - [x] Custom date cell - [x] Custom header view and collection view - [x] Custom calendar localization - [x] Ability to set a divider line - [x] UIMenu supports in event view (iOS 14.0 and above)

Need Help?

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.

Requirements

  • iOS 10.0+, iPadOS 10.0+, MacOS 10.15+ (Supports Mac Catalyst)
  • Swift 5.0+

Installation

KVKCalendar is available through CocoaPods or Carthage or Swift Package Manager.

CocoaPods

pod 'KVKCalendar'

Adding Pods to an Xcode project

Carthage

github "kvyatkovskys/KVKCalendar"

Adding Frameworks to an Xcode project

Swift Package Manager (Xcode 12 or higher)

  1. In Xcode navigate to FileSwift PackagesAdd Package Dependency...
  2. Select a project
  3. Paste the repository URL (
    https://github.com/kvyatkovskys/KVKCalendar.git
    ) and click Next.
  4. For Rules, select Version (Up to Next Major) and click Next.
  5. Click Finish.

Adding Package Dependencies to Your App

Usage for UIKit

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 viewDidLayoutSubviews() {
    super.viewDidLayoutSubviews()
    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({ $0.transform() }) 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).
swift
func dequeueCell(date: Date?, 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
    }
}

Usage for SwiftUI

Add a new

SwiftUI
file and import
KVKCalendar
. Create a struct
CalendarDisplayView
and declare the protocol
UIViewRepresentable
for connection
UIKit
with
SwiftUI
.
import SwiftUI
import KVKCalendar

struct CalendarDisplayView: UIViewRepresentable { @Binding var events: [Event]

private var calendar: CalendarView = {
    return CalendarView(frame: frame, style: style)
}()

func makeUIView(context: UIViewRepresentableContext<calendardisplayview>) -&gt; 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() -&gt; CalendarDisplayView.Coordinator {
    Coordinator(self)
}

public init(events: Binding) {
    self._events = events
}

// MARK: Calendar DataSource and Delegate
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]) -&gt; [Event] {
        return events
    }
}

}

Create a new

SwiftUI
file and add
CalendarDisplayView
to
body
.
import SwiftUI

struct CalendarContentView: View { @State var events: [Event] = []

var body: some View {
    NavigationView {
        CalendarDisplayView(events: $events)
    }
}

}

Styles

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 = []
}

Author

Sergei Kviatkovskii

License

KVKCalendar is available under the MIT license

We use cookies. If you continue to browse the site, you agree to the use of cookies. For more information on our use of cookies please see our Privacy Policy.