All Projects β†’ vinhnx β†’ Shift

vinhnx / Shift

Licence: MIT license
Light-weight EventKit wrapper.

Programming Languages

swift
15916 projects

Projects that are alternatives of or similar to Shift

Ea Async
EA Async implements async-await methods in the JVM.
Stars: ✭ 1,085 (+3400%)
Mutual labels:  asynchronous, concurrency, async-await
NYTimes-iOS
πŸ—½ NY Times is an Minimal News πŸ—ž iOS app πŸ“± built to describe the use of SwiftSoup and CoreData with SwiftUIπŸ”₯
Stars: ✭ 152 (+390.32%)
Mutual labels:  combine, swiftui, swift5
JewelCase
This is the source code for JewelCase, a sample app demonstrating how to use SwiftUI and Firebase together. This slide deck discusses the architecture of the app: https://www.slideshare.net/peterfriese/building-swiftui-apps-with-firebase
Stars: ✭ 42 (+35.48%)
Mutual labels:  combine, swiftui, swift5
Carekit
CareKit is an open source software framework for creating apps that help people better understand and manage their health.
Stars: ✭ 2,142 (+6809.68%)
Mutual labels:  swift-package-manager, combine, swift5
LongWeekend-iOS
πŸ–πŸ“± LongWeekend is iOS Application that supports checking long weekends when taking a vacation in Japan
Stars: ✭ 19 (-38.71%)
Mutual labels:  combine, swiftui, swift5
CallofDuty.py
Asynchronous, object-oriented Python wrapper for the Call of Duty API.
Stars: ✭ 86 (+177.42%)
Mutual labels:  wrapper, asynchronous
Combinative
UI event handling using Apple's combine framework.
Stars: ✭ 106 (+241.94%)
Mutual labels:  swift-package-manager, swift5
SwiftUI-Color-Kit
SwiftUI Color Pickers, Gradient Pickers And All The Utilities Needed To Make Your Own!
Stars: ✭ 120 (+287.1%)
Mutual labels:  swift-package-manager, swiftui
Project01-C-User-Event-Collector
πŸ’œπŸŽ· 넀이버 VIBE μ‚¬μš©μž 이벀트 μˆ˜μ§‘κΈ° πŸŽ·πŸ’œ
Stars: ✭ 21 (-32.26%)
Mutual labels:  combine, swiftui
core-data-model-description
Declarative way to describe a Core Data model in code.
Stars: ✭ 60 (+93.55%)
Mutual labels:  swift-package-manager, swift5
GameKitUI.swift
GameKit (GameCenter) for SwiftUI
Stars: ✭ 29 (-6.45%)
Mutual labels:  swiftui, swift5
ScrollViewProxy
ScrollViewProxy for SwiftUI on iOS 13 and up
Stars: ✭ 135 (+335.48%)
Mutual labels:  swift-package-manager, swiftui
LunarCalendar
A lightweight macOS App for displaying calendar and time
Stars: ✭ 82 (+164.52%)
Mutual labels:  calendar, swiftui
await-lock
Mutex locks for async functions
Stars: ✭ 66 (+112.9%)
Mutual labels:  concurrency, async-await
JSONPreview
🎨 A view that previews JSON in highlighted form, it also provides the ability to format and collapse nodes.
Stars: ✭ 21 (-32.26%)
Mutual labels:  swift-package-manager, swift5
SwiftUI-App
This swiftUI Demo is very simple & easy to understand. This swiftUI demo includes On-boarding screens, login screen, forgot password screen, sign up screen, home & logout.
Stars: ✭ 175 (+464.52%)
Mutual labels:  swiftui, swift5
Rick-and-Morty-iOS-App
This is a sample iOS 13+ UIKit - Combine project.
Stars: ✭ 21 (-32.26%)
Mutual labels:  async-await, combine
Chat
A basic SwiftUI chat app that leverages the new URLSessionWebSocketTask.
Stars: ✭ 22 (-29.03%)
Mutual labels:  combine, swiftui
swift-composable-app-example
Example iOS app built with module composition in mind.
Stars: ✭ 79 (+154.84%)
Mutual labels:  swift-package-manager, swiftui
SwiftGradients
Useful extensions for UIViews and CALayer classes to add beautiful color gradients.
Stars: ✭ 15 (-51.61%)
Mutual labels:  swift-package-manager, swift5

Shift

Light-weight EventKit wrapper.


Swift

Shift is a light-weight concurrency wrapper for EventKit:

  • Concurrency ready with async/await. (tag: 0.7.0)
  • Tranditional, Result completion handler if preferred (tag: 0.6.0)
  • Thread-safe.
  • SwiftUI supported.

Requirement

  • iOS 15.0 for async/await, tag 0.7.0
  • iOS 14.0 and below for Result-based, tag <0.6.0
  • Swift version 5.5
  • Xcode 13.1

Install

This component is built using Swift Package Manager, it is pretty straight forward to use:

  1. In Xcode (11+), open your project and navigate to File > Swift Packages > Add Package Dependency...
  2. Paste the repository URL (https://github.com/vinhnx/Shift) and click Next.
  3. For Rules, select Version, in here, you can choose either:
  • Async/await => tag 0.7.0
  • Result-based completion handler => tag 0.6.0
  1. Click Finish to resolve package into your Xcode project.

Screen Shot 2021-08-15 at 11 28 54

Tag Version:

Concurrency support is now ready, in tag 0.7.0

In order to use old Result-based completion hanlders, please use tag 0.6.0.

Getting Started

First thing first:

  • Add Calendar usage description to your app's Info.plist to request for user's Calendars access.
<key>NSCalendarsUsageDescription</key>
	<string>&quot;$(PRODUCT_NAME) needs your permission to create events&quot;</string>
  • (Optional) configure own calendar name to request access to, preferrable in AppDelegate's didFinishLaunchingWithOptions (Swift) or App's 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
    }
}

in SwiftUI App, first import Shift, then configure your app's name to differntiate the name of your app's calendar in system's EventKit.

import SwiftUI
import Shift

@main
struct MyApp: App {
    init() {
        Shift.configureWithAppName("MyApp")
    }

    var body: some Scene {
        WindowGroup {
            ContentView()
        }
    }
}

A quick NOTE about concurrency

Since async functions can only be called on concurrency context, if you call async function inside synchornouse context, Xcode will throws an error:

Screen Shot 2021-11-29 at 11 35 39

So, there are two ways to awaiting for concurrency result, base on context:

  • Inside async function
func doSomethingAsync() async {
    // ... other works
    let events = try? await Shift.shared.fetchEvents(for: Date())
    // ... other works
}
  • Inside Task closure:
func regularFunction() {
    // ... other works

    Task {
        let events = try? await Shift.shared.fetchEvents(for: Date())
        // then...
    }

    // ... other works
}

Either is fine, base on caller's context.

You can read more about Task here https://developer.apple.com/documentation/swift/task.

In SwiftUI views, you can call async functions inside View' .task modifier:

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

You can read more about SwiftUI's .task modifier here https://developer.apple.com/documentation/swiftui/view/task(priority:_:).


Usage Example

Fetch list of events for a particular date:

async/await (NEW)

inside regular async function:

func fetchEvents() async {
    do {
        let events = try await Shift.shared.fetchEvents(for: Date()) // await for events fetching
    } catch {
        print(error) // handle error
    }
}

or standalone:

Task {
    let events = try? await Shift.shared.fetchEvents(for: Date()) // await for events fetching
}

Result-based completion handlers (old pattern, but still doable if you preferred this to 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
    }
}

Create Event:

async/await

inside regular async function:

func myAsyncFunction() async {
    try? await Shift.shared.createEvent("Be happy!", startDate: startTime, endDate: endTime)
}

or standalone:

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

Delete event:

async/await

inside regular async function:

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

or standalone:

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 Example

Shift is conformed ObservableObject with an @Published events property, so it's straight-forward to use in SwiftUI binding mechanism.

Result-based example:

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 example:

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

Apps currently using Shift

  • Clendar - Clendar - universal calendar app. Written in SwiftUI. Available on App Store. MIT License.

(add yours here)


Help, feedback or suggestions?

Feel free to open an issue or contact me on Twitter for discussions, news & announcements & other projects. πŸš€

I hope you like it! :)

Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].