请注意,我正在尝试在iPhone 13 Pro Max模拟器上添加约会,在那里我无法使用XCode 13创建新事件。
我的代码一直基于这个示例,
https://github.com/richardtop/CalendarApp这是CalendarViewController.swift
的源代码,我认为createNewEvent
是一个关键功能:
import UIKit
import CalendarKit
import EventKit
import EventKitUI
final class CalendarViewController: DayViewController, EKEventEditViewDelegate {
private var eventStore = EKEventStore()
override func viewDidLoad() {
super.viewDidLoad()
title = "Calendar"
// The app must have access to the user's calendar to show the events on the timeline
requestAccessToCalendar()
// Subscribe to notifications to reload the UI when
subscribeToNotifications()
}
private func requestAccessToCalendar() {
// Request access to the events
eventStore.requestAccess(to: .event) { [weak self] granted, error in
// Handle the response to the request.
DispatchQueue.main.async {
guard let self = self else { return }
self.initializeStore()
self.subscribeToNotifications()
self.reloadData()
}
}
}
private func subscribeToNotifications() {
NotificationCenter.default.addObserver(self,
selector: #selector(storeChanged(_:)),
name: .EKEventStoreChanged,
object: eventStore)
}
private func initializeStore() {
eventStore = EKEventStore()
}
@objc private func storeChanged(_ notification: Notification) {
reloadData()
}
// MARK: - DayViewDataSource
// This is the `DayViewDataSource` method that the client app has to implement in order to display events with CalendarKit
override func eventsForDate(_ date: Date) -> [EventDescriptor] {
// The `date` always has it's Time components set to 00:00:00 of the day requested
let startDate = date
var oneDayComponents = DateComponents()
oneDayComponents.day = 1
// By adding one full `day` to the `startDate`, we're getting to the 00:00:00 of the *next* day
let endDate = calendar.date(byAdding: oneDayComponents, to: startDate)!
let predicate = eventStore.predicateForEvents(withStart: startDate, // Start of the current day
end: endDate, // Start of the next day
calendars: nil) // Search in all calendars
let eventKitEvents = eventStore.events(matching: predicate) // All events happening on a given day
let calendarKitEvents = eventKitEvents.map(EKWrapper.init)
return calendarKitEvents
}
// MARK: - DayViewDelegate
// MARK: Event Selection
override func dayViewDidSelectEventView(_ eventView: EventView) {
guard let ckEvent = eventView.descriptor as? EKWrapper else {
return
}
presentDetailViewForEvent(ckEvent.ekEvent)
}
private func presentDetailViewForEvent(_ ekEvent: EKEvent) {
let eventController = EKEventViewController()
eventController.event = ekEvent
eventController.allowsCalendarPreview = true
eventController.allowsEditing = true
navigationController?.pushViewController(eventController,
animated: true)
}
// MARK: Event Editing
override func dayView(dayView: DayView, didLongPressTimelineAt date: Date) {
// Cancel editing current event and start creating a new one
endEventEditing()
let newEKWrapper = createNewEvent(at: date)
create(event: newEKWrapper, animated: true)
}
private func createNewEvent(at date: Date) -> EKWrapper {
let newEKEvent = EKEvent(eventStore: eventStore)
newEKEvent.calendar = eventStore.defaultCalendarForNewEvents
var components = DateComponents()
components.hour = 1
let endDate = calendar.date(byAdding: components, to: date)
newEKEvent.startDate = date
newEKEvent.endDate = endDate
newEKEvent.title = "New event"
let newEKWrapper = EKWrapper(eventKitEvent: newEKEvent)
newEKWrapper.editedEvent = newEKWrapper
return newEKWrapper
}
override func dayViewDidLongPressEventView(_ eventView: EventView) {
guard let descriptor = eventView.descriptor as? EKWrapper else {
return
}
endEventEditing()
beginEditing(event: descriptor,
animated: true)
}
override func dayView(dayView: DayView, didUpdate event: EventDescriptor) {
guard let editingEvent = event as? EKWrapper else { return }
if let originalEvent = event.editedEvent {
editingEvent.commitEditing()
if originalEvent === editingEvent {
// If editing event is the same as the original one, it has just been created.
// Showing editing view controller
presentEditingViewForEvent(editingEvent.ekEvent)
} else {
// If editing event is different from the original,
// then it's pointing to the event already in the `eventStore`
// Let's save changes to oriignal event to the `eventStore`
try! eventStore.save(editingEvent.ekEvent,
span: .thisEvent)
}
}
reloadData()
}
private func presentEditingViewForEvent(_ ekEvent: EKEvent) {
let eventEditViewController = EKEventEditViewController()
eventEditViewController.event = ekEvent
eventEditViewController.eventStore = eventStore
eventEditViewController.editViewDelegate = self
present(eventEditViewController, animated: true, completion: nil)
}
override func dayView(dayView: DayView, didTapTimelineAt date: Date) {
endEventEditing()
}
override func dayViewDidBeginDragging(dayView: DayView) {
endEventEditing()
}
// MARK: - EKEventEditViewDelegate
func eventEditViewController(_ controller: EKEventEditViewController, didCompleteWith action: EKEventEditViewAction) {
endEventEditing()
reloadData()
controller.dismiss(animated: true, completion: nil)
}
}
它达到了我可以添加约会的地步,但顶部RHS中的Add
按钮不起作用,我无法编辑New event
文本。
对我来说,问题不在于警告。我只是想能够使用CalendarKit
创建一个约会。有人有什么建议吗?TIA。
问题是我选择了Device
->Erase All Content and Settings...
在模拟器中允许访问我的日历后,但当我在那之后再次调试应用程序时,所以我想这意味着它失去了对我的日历的访问权限,但由于某种原因,它没有请求访问日历。
当我在不同的设备上测试时,它在第一次运行时请求许可,之后事情正常运行。