Shift

轻量级 EventKit 封装。


Swift

Shift 是一个用于 EventKit 的轻量级并发封装。

Shift 目前正被 Clendar 应用使用。

要求

安装

此组件使用 Swift Package Manager 构建,使用起来非常简单直接

  1. 在 Xcode(11+)中,打开您的项目并导航到 File > Swift Packages > Add Package Dependency...
  2. 粘贴仓库 URL (https://github.com/vinhnx/Shift) 并点击 Next。
  3. 对于 Rules,选择 Version,在这里,您可以选择
  1. 点击 Finish 以将软件包解析到您的 Xcode 项目中。

Screen Shot 2021-08-15 at 11 28 54

标签版本

并发支持现已准备就绪,在标签 0.7.0

要使用旧的基于 Result 的完成处理程序,请使用标签 0.6.0

开始使用

首先:

<key>NSCalendarsUsageDescription</key>
	<string>&quot;$(PRODUCT_NAME) needs your permission to create events&quot;</string>

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 将抛出错误

Screen Shot 2021-11-29 at 11 35 39

因此,根据上下文,有两种方法可以 await 并发结果

func doSomethingAsync() async {
    // ... other works
    let events = try? await Shift.shared.fetchEvents(for: Date())
    // ... other works
}
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/await (新)

在常规 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
}

基于 Result 的完成处理程序(旧模式,但如果您更喜欢 async/await,仍然可行)

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/await

在常规 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)
}

Result

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/await

在常规 async 函数内部

func myAsyncFunction() async {
    try? await Shift.shared.deleteEvent(identifier: eventID)
}

或独立使用

Task {
    try? await Shift.shared.deleteEvent(identifier: eventID)
}

Result

Shift.shared.deleteEvent(identifier: eventID) { result in
    switch result {
    case let .success: print("done!") // deleted event
    case let .failure(error): print(error) // handle error
    }
}

SwiftUI 示例

Shift 遵循 ObservableObject 协议,并具有 @Published events 属性,因此可以直接在 SwiftUI 绑定机制中使用。

基于 Result 的示例

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()
        }
    }
}

async/await 示例

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() 
        }
    }
}

目前正在使用 Shift 的应用

(在此处添加您的应用)


帮助、反馈或建议?

请随时提出 issue 或在 Twitter 上联系我进行讨论、获取新闻和公告以及了解其他项目。🚀

希望你喜欢!:)