Skip to content

A modern Swift library for local notification management wrapping UNUserNotificationCenter with async/await, fluent API, deep linking, and repeating schedules.

Notifications You must be signed in to change notification settings

DeepakPal25/NotificationKit

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

2 Commits
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

NotificationKit

A type-safe, async/await Swift wrapper around Apple's UserNotifications framework. Schedule local notifications, handle user responses, and manage permissions with a clean, modern API.

Features

  • Async/Await — Modern concurrency throughout
  • Thread-Safe — Fully Sendable-compliant
  • Fluent Builder API — Chain methods to build notification content
  • Multiple Triggers — Time interval, calendar, and location (iOS)
  • Repeating Schedules — Daily, weekly, custom intervals
  • Interactive Actions — Categories with buttons and text input
  • Deep Linking — Built-in deep link support via userInfo
  • Response Streaming — AsyncStream for handling user interactions
  • Foreground Presentation — Control in-app notification display

Requirements

Platform Minimum Version
iOS 15.0
macOS 12.0
Swift 6.2

Installation

Swift Package Manager

Add NotificationKit to your Package.swift:

dependencies: [
    .package(url: "https://github.com/user/NotificationKit.git", from: "1.0.0")
]

Then add it as a dependency to your target:

.target(
    name: "MyApp",
    dependencies: ["NotificationKit"]
)

Or in Xcode: File > Add Package Dependencies and paste the repository URL.

Quick Start

import NotificationKit

// 1. Request permission
let granted = try await NotificationKit.shared.requestPermission()

// 2. Create content
let content = NotificationContent(title: "Hello", body: "Your first notification!")
    .withSound(.default)

// 3. Schedule
try await NotificationKit.shared.schedule(
    id: "hello",
    content: content,
    trigger: .timeInterval(5)
)

Usage

Requesting Permission

// Default options (alert, sound, badge)
let granted = try await NotificationKit.shared.requestPermission()

// Custom options
let granted = try await NotificationKit.shared.requestPermission(
    options: [.alert, .sound, .badge, .criticalAlert]
)

// Check current status
let permission = await NotificationKit.shared.currentPermission()
switch permission {
case .authorized:    print("Authorized")
case .denied:        print("Denied")
case .notDetermined: print("Not yet asked")
case .provisional:   print("Provisional")
}

Building Notification Content

Use the fluent builder API to configure notifications:

let content = NotificationContent(title: "Meeting Reminder", body: "Standup in 5 minutes")
    .withSubtitle("Engineering Team")
    .withSound(.default)
    .withBadge(1)
    .withCategory("MEETING")
    .withDeepLink(URL(string: "myapp://meetings/123")!)
    .withUserInfo(key: "priority", value: "high")
    .withThreadIdentifier("meetings")

Scheduling Notifications

Time Interval

// Fire once after 60 seconds
try await NotificationKit.shared.schedule(
    id: "reminder",
    content: content,
    trigger: .timeInterval(60)
)

// Repeat every 2 hours
try await NotificationKit.shared.schedule(
    id: "recurring",
    content: content,
    trigger: .timeInterval(7200, repeats: true)
)

Calendar Date

var dateComponents = DateComponents()
dateComponents.year = 2026
dateComponents.month = 3
dateComponents.day = 15
dateComponents.hour = 9
dateComponents.minute = 0

try await NotificationKit.shared.schedule(
    id: "birthday",
    content: content,
    trigger: .calendar(dateComponents)
)

Repeat Rules

// Daily at 9:30 AM
try await NotificationKit.shared.schedule(
    id: "daily",
    content: content,
    repeatRule: .daily(hour: 9, minute: 30)
)

// Every Monday at 10:00 AM
try await NotificationKit.shared.schedule(
    id: "weekly",
    content: content,
    repeatRule: .weekly(weekday: 2, hour: 10, minute: 0)
)

// Every 5 minutes
try await NotificationKit.shared.schedule(
    id: "interval",
    content: content,
    repeatRule: .interval(300)
)

Location (iOS only)

#if os(iOS)
import CoreLocation

let region = CLCircularRegion(
    center: CLLocationCoordinate2D(latitude: 37.33, longitude: -122.01),
    radius: 100,
    identifier: "office"
)
region.notifyOnEntry = true

try await NotificationKit.shared.schedule(
    id: "geofence",
    content: content,
    trigger: .location(region)
)
#endif

Interactive Actions & Categories

// Define actions
let reply = NotificationAction(identifier: "REPLY", title: "Reply", options: [.foreground])
let delete = NotificationAction(identifier: "DELETE", title: "Delete", options: [.destructive])
let textInput = NotificationAction.textInput(
    identifier: "QUICK_REPLY",
    title: "Quick Reply",
    buttonTitle: "Send",
    placeholder: "Type a message..."
)

// Register a category
let messageCategory = NotificationCategory(
    identifier: "MESSAGE",
    actions: [reply, delete, textInput]
)
NotificationKit.shared.registerCategories([messageCategory])

// Assign category to content
let content = NotificationContent(title: "New Message", body: "Hey, are you free?")
    .withCategory("MESSAGE")

Handling Responses

Task {
    for await response in NotificationKit.shared.responses {
        switch response.action {
        case .default:
            print("User tapped notification: \(response.notificationIdentifier)")
        case .dismiss:
            print("Notification dismissed")
        case .custom(let actionId):
            print("Custom action: \(actionId)")
            if let text = response.userText {
                print("User typed: \(text)")
            }
        }

        // Handle deep links
        if let url = response.deepLinkURL {
            navigateTo(url)
        }
    }
}

Foreground Presentation

// Show banner and play sound when app is in foreground
NotificationKit.shared.setForegroundPresentation([.banner, .sound])

Cancellation

// Cancel a specific notification
NotificationKit.shared.cancel(id: "reminder")

// Cancel all notifications
NotificationKit.shared.cancelAll()

Error Handling

do {
    try await NotificationKit.shared.schedule(
        id: "test",
        content: content,
        trigger: .timeInterval(-1) // invalid
    )
} catch let error as NotificationError {
    switch error {
    case .permissionDenied:
        print("Permission denied")
    case .invalidTrigger(let reason):
        print("Invalid trigger: \(reason)")
    case .schedulingFailed(let reason):
        print("Scheduling failed: \(reason)")
    case .categoryRegistrationFailed(let reason):
        print("Category registration failed: \(reason)")
    }
}

API Reference

Type Description
NotificationKit Main entry point. Singleton via .shared or create custom instances.
NotificationContent Notification payload with fluent builder methods.
NotificationTrigger .timeInterval, .calendar, .location (iOS).
NotificationRepeatRule .daily, .weekly, .interval, .custom repeat schedules.
NotificationCategory Groups interactive actions for a notification type.
NotificationAction A button or text input action on a notification.
NotificationResponse User interaction data including action, deep link, and text input.
NotificationPermission Permission status: .authorized, .denied, .notDetermined, .provisional.
NotificationPermissionOptions Options to request: .alert, .sound, .badge, .criticalAlert, .provisional.
NotificationError Typed errors for permission, trigger, scheduling, and category failures.

Example App

A full SwiftUI demo app is included in the Example/ directory. It demonstrates:

  • Requesting and displaying permission status
  • Scheduling simple, rich, and deep-link notifications
  • Registering interactive action categories
  • Handling notification responses via AsyncStream
  • Repeating notifications (interval and daily)
  • Cancelling notifications and enabling foreground display

To run it:

cd Example
swift build        # or open in Xcode

Or open the Example/ folder in Xcode and run the NotificationKitDemo target on a simulator or device.

License

MIT License. See LICENSE for details.

About

A modern Swift library for local notification management wrapping UNUserNotificationCenter with async/await, fluent API, deep linking, and repeating schedules.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages