轻量级 EventKit 封装。
Shift 是一个用于 EventKit 的轻量级并发封装。
async
/await
并发使用。(标签:0.7.0
)Result
的完成处理程序(标签:0.6.0
)Shift 目前正被 Clendar 应用使用。
0.7.0
0.6.0
此组件使用 Swift Package Manager 构建,使用起来非常简单直接
0.7.0
0.6.0
并发支持现已准备就绪,在标签 0.7.0
中
要使用旧的基于 Result 的完成处理程序,请使用标签 0.6.0
。
首先:
<key>NSCalendarsUsageDescription</key>
<string>"$(PRODUCT_NAME) needs your permission to create events"</string>
AppDelegate
的 didFinishLaunchingWithOptions
(Swift) 或 App
的 init()
(SwiftUI) 中配置Swift AppDelegate
import UIKit
@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
// Override point for customization after application launch.
Shift.configureWithAppName("MyApp")
return true
}
}
在 SwiftUI App 中,首先 import Shift
,然后配置您的应用名称,以便在系统的 EventKit 中区分您应用的日历名称。
import SwiftUI
import Shift
@main
struct MyApp: App {
init() {
Shift.configureWithAppName("MyApp")
}
var body: some Scene {
WindowGroup {
ContentView()
}
}
}
由于 async
函数只能在并发上下文中调用,如果您在同步上下文中调用 async
函数,Xcode 将抛出错误
因此,根据上下文,有两种方法可以 await
并发结果
async
函数内部func doSomethingAsync() async {
// ... other works
let events = try? await Shift.shared.fetchEvents(for: Date())
// ... other works
}
Task
闭包内部func regularFunction() {
// ... other works
Task {
let events = try? await Shift.shared.fetchEvents(for: Date())
// then...
}
// ... other works
}
两者都可以,根据调用者的上下文。
您可以在此处阅读有关 Task 的更多信息 https://developer.apple.com/documentation/swift/task。
在 SwiftUI 视图中,您可以在 View 的 .task
修饰符内部调用 async
函数
import EventKit
import SwiftUI
import Shift
struct ContentView: View {
@StateObject var eventKitWrapper = Shift.shared
@State private var selectedEvent: EKEvent?
var body: some View {
LazyVStack(alignment: .leading, spacing: 10) {
ForEach(eventKitWrapper.events, id: \.self) { event in
Text(event: event)
}
}
.padding()
.task { // wrap async call inside .task modifier
try? await eventKitWrapper.fetchEventsForToday()
}
}
}
您可以在此处阅读有关 SwiftUI 的
.task
修饰符的更多信息 https://developer.apple.com/documentation/swiftui/view/task(priority:_:)。
获取特定日期的事件列表
在常规 async 函数内部
func fetchEvents() async {
do {
let events = try await Shift.shared.fetchEvents(for: Date()) // await for events fetching
} catch {
print(error) // handle error
}
}
或独立使用
Task {
let events = try? await Shift.shared.fetchEvents(for: Date()) // await for events fetching
}
Shift.shared.fetchEvents(for: Date()) { result in
switch result {
case let .success(events): print(events) // got events
case let .failure(error): print(error) // handle error
}
}
Shift.shared.fetchEventsRangeUntilEndOfDay(from: Date()) { result in
switch result {
case let .success(events): print(events) // got events
case let .failure(error): print(error) // handle error
}
}
创建事件
在常规 async 函数内部
func myAsyncFunction() async {
try? await Shift.shared.createEvent("Be happy!", startDate: startTime, endDate: endTime)
}
或独立使用
Task {
try? await Shift.shared.createEvent("Be happy!", startDate: startTime, endDate: endTime)
}
Shift.shared.createEvent("Be happy!", startDate: startTime, endDate: endTime) { result in
switch result {
case let .success(event): print(event) // created event
case let .failure(error): print(error) // handle error
}
}
删除事件
在常规 async 函数内部
func myAsyncFunction() async {
try? await Shift.shared.deleteEvent(identifier: eventID)
}
或独立使用
Task {
try? await Shift.shared.deleteEvent(identifier: eventID)
}
Shift.shared.deleteEvent(identifier: eventID) { result in
switch result {
case let .success: print("done!") // deleted event
case let .failure(error): print(error) // handle error
}
}
Shift 遵循 ObservableObject
协议,并具有 @Published
events
属性,因此可以直接在 SwiftUI 绑定机制中使用。
import EventKit
import SwiftUI
import Shift
struct ContentView: View {
@StateObject var eventKitWrapper = Shift.shared
@State private var selectedEvent: EKEvent?
var body: some View {
LazyVStack(alignment: .leading, spacing: 10) {
ForEach(eventKitWrapper.events, id: \.self) { event in
Text(event: event)
}
}
.padding()
.onAppear {
eventKitWrapper.fetchEventsForToday()
}
}
}
import EventKit
import SwiftUI
import Shift
struct ContentView: View {
@StateObject var eventKitWrapper = Shift.shared
@State private var selectedEvent: EKEvent?
var body: some View {
LazyVStack(alignment: .leading, spacing: 10) {
ForEach(eventKitWrapper.events, id: \.self) { event in
Text(event: event)
}
}
.padding()
.task {
try? await eventKitWrapper.fetchEventsForToday()
}
}
}
请随时提出 issue 或在 Twitter 上联系我进行讨论、获取新闻和公告以及了解其他项目。🚀
希望你喜欢!:)