Swiftpack.co - Miiha/composable-user-notifications as Swift Package

Swiftpack.co is a collection of thousands of indexed Swift packages. Search packages.
See all packages published by Miiha.
Miiha/composable-user-notifications 0.3.0
A wrapper around UNUserNotificationCenter that makes it easy to use from a reducer, and easy to write tests for how your logic interacts with UNUserNotificationCenter's functionality.
⭐️ 13
🕓 4 weeks ago
iOS macOS watchOS tvOS
.package(url: "https://github.com/Miiha/composable-user-notifications.git", from: "0.3.0")

Composable User Notifications

Composable User Notifications is library that bridges the Composable Architecture and User Notifications.

This library is modelling it's dependency using swift concurrency since version 0.3.0.

Example

Check out the Example demo to see how ComposableUserNotifications can be used.

Basic usage

To handle incoming user notification you can observe the UNUserNotificationCenterDelegate actions through UserNotificationClient.DelegateAction of the UserNotificationClient.delegate.

import ComposableUserNotifications

struct App: ReducerProtocol {
  enum Action {
  case userNotification(UserNotificationClient.DelegateAction)
  // Your domain's other actions:
...

The UserNotificationClient.DelegateAction holds the actions

  • for handling foreground notifications willPresentNotification(_:completion)
  • to process the user's response to a delivered notification didReceiveResponse(_:completionHandler:)
  • to display the in-app notification settings openSettingsForNotification(_:)

The wrapper around apple's UNUserNotificationCenter UserNotificationClient, is available on the DependencyValues and can be retrieved on using @Dependency(\.userNotifications).

At some point you need to subscribe to UserNotificationClient.DelegateAction in order not to miss any UNUserNotificationCenterDelegate related actions. This can be done early after starting the application.

func reduce(into state: inout State, action: Action) -> EffectTask<Action> {
  switch action {
  case let .didFinishLaunching(notification):
    ...
    return .run { send in
        for await event in self.userNotifications.delegate() {
          await send(.userNotifications(event))
        }
      }
    }
  }
}

When subscribing to these actions we can handle them as follows.

...
  case let .userNotification(.willPresentNotification(notification, completion)):
    return .fireAndForget {
      completion([.list, .banner, .sound])
    }

  case let .userNotification(.didReceiveResponse(response, completion)):
    return .fireAndForget {
      completion()
    }

  case .userNotification(.openSettingsForNotification):
    return .none
...

To request authorization from the user you can use requestAuthorization and handle the users choice as a new action.

func reduce(into state: inout State, action: Action) -> EffectTask<Action> {
  switch action {
  case .didFinishLaunching:
    return .task {
      .requestAuthorizationResponse(
        TaskResult {
          try await self.userNotifications.requestAuthorization([.alert, .badge, .sound])
        }
      )
    }
  }
  ...
}

Adding notification requests is also straight forward. It can be done using UNNotificationRequest in conjunction with UserNotificationClient.add(_:).

  case .tappedScheduleButton:
    let content = UNMutableNotificationContent()
    content.title = "Example title"
    content.body = "Example body"

    let request = UNNotificationRequest(
      identifier: "example_notification",
      content: content,
      trigger: UNTimeIntervalNotificationTrigger(timeInterval: 5, repeats: false)
    )

    return .task {
      await self.userNotifications
        .removePendingNotificationRequestsWithIdentifiers(["example_notification"])
      return await .addNotificationResponse(
        TaskResult {
          Unit(try await self.userNotifications.add(request))
        }
      )
    }
  ...

All API calls to UNUserNotificationCenter are available through UserNotificationClient. The true power of this approach lies in the testability of your notification logic. For more info around testability have a look at ExampleTests.swift.

Installation

You can add ComposableUserNotifications to an Xcode project by adding it as a package dependency.

  1. From the File menu, select Swift Packages › Add Package Dependency…
  2. Enter "https://github.com/miiha/composable-user-notifications" into the package repository URL text field

License

This library is released under the MIT license. See LICENSE for details.

GitHub

link
Stars: 13
Last commit: 3 weeks ago
jonrohan Something's broken? Yell at me @ptrpavlik. Praise and feedback (and money) is also welcome.

Release Notes

0.3.0
4 weeks ago

Merged pull requests:

  • Updates client to swift concurrency and dependency key #5 (Miiha) (thanks @andreyz)

Swiftpack is being maintained by Petr Pavlik | @ptrpavlik | @swiftpackco | API | Analytics