Robin is a multi-platform notification interface for iOS, watchOS, and macOS that handles UserNotifications behind the scenes.
- iOS 10.0+
- watchOS 3.0+
- macOS 10.14+
- Xcode 11.1+
- Swift 4.2+
- If you need help or have a question, use 'robin' tag on Stack Overflow.
- If you found a bug or have a feature request, please open an issue.
Please do not open a pull request until a contribution guide is published.
Robin is available through both Swift Package Manager and CocoaPods.
To install using SPM:
.package(url: "https://github.com/ahmdx/Robin", from: "0.96.1"),CocoaPods:
pod 'Robin', '~> 0.96.1'And if you want to include the test suite in your project:
pod 'Robin', '~> 0.96.1', :testspecs => ['Tests']import RobinBefore using Robin, you need to request permission to send notifications to users. The following requests badge, sound, and alert permissions. For all available options, refer to UNAuthorizationOptions.
Robin.settings.requestAuthorization(forOptions: [.badge, .sound, .alert]) { grant, error in
// Handle authorization or error
}To query for the app's notification settings, you can use Robin.settings:
let alertStyle = Robin.settings.alertStyleNote:
alertStyleis not available on watchOS.
let authorizationStatus = Robin.settings.authorizationStatuslet enabledSettings = Robin.settings.enabledSettingsNote: This returns an option set of all the enabled settings. If some settings are not included in the set, they may be disabled or not supported. If you would like to know if some specific setting is enabled, you can use
enabledSettings.contains(.sound)for example. For more details, refer toRobinSettingsOptions.
let showPreviews = Robin.settings.showPreviewsNote:
showPreviewsis not available on watchOS.
Robin automatically updates information about the app's settings when the app goes into an inactive state and becomes active again to avoid unnecessary queries. If you would like to override this behavior and update the information manually, you can use forceRefresh().
Robin.settings.forceRefresh()Note: Robin on watchOS does not support automatic settings refresh.
Scheduling notifications via Robin is carried over by manipulating RobinNotification objects. To create a RobinNotification object, simply call its initializer.
init(identifier: String = default, body: String, trigger: RobinNotificationTrigger = default)Example notification, with a unique identifier, to be fired an hour from now.
let notification = RobinNotification(body: "A notification", trigger: .date(.next(hours: 1)))Note:
next(minutes:),next(hours:), andnext(days:)are part of aDateextension.
Example notification, with a unique identifier, to be fired when entering a region.
/// https://developer.apple.com/documentation/usernotifications/unlocationnotificationtrigger
let center = CLLocationCoordinate2D(latitude: 37.335400, longitude: -122.009201)
let region = CLCircularRegion(center: center, radius: 2000.0, identifier: "Headquarters")
region.notifyOnEntry = true
region.notifyOnExit = false
let notification = RobinNotification(body: "A notification", trigger: .location(region))Note: For the system to deliver location notifications, the app should be authorized to use location services, see here. Robin does not check whether the required permissions are granted before scheduling a location notification. Location notifications are not available on either macOS or watchOS.
The following table summarizes all RobinNotification properties.
| Property | Type | Description |
|---|---|---|
| badge | NSNumber? |
The number the notification should display on the app icon. |
| body | String! |
The body string of the notification. |
| delivered | Bool |
The delivery status of the notification. read-only |
| identifier[1] | String! |
A string assigned to the notification for later access. |
| scheduled | Bool |
The status of the notification. read-only |
| sound | RobinNotificationSound |
The sound name of the notification. not available on watchOS |
| threadIdentifier | String? |
The identifier used to visually group notifications together. |
| title | String? |
The title string of the notification. |
| trigger | Enum |
The trigger that causes the notification to fire. One of date or location. |
| userInfo[2] | [AnyHashable : Any]! |
A dictionary that holds additional information. |
[1] identifier is read-only after RobinNotification is initialized.
[2] To add and remove keys in userInfo, use setUserInfo(value: Any, forKey: AnyHashable) and removeUserInfoValue(forKey: AnyHashable) respectively.
After creating a RobinNotification object, it can be scheduled using schedule(notification: RobinNotification).
let scheduledNotification = Robin.scheduler.schedule(notification: notification)Now scheduledNotification is a valid RobinNotification object if it is successfully scheduled or nil otherwise.
Simply retrieve a scheduled notification by calling notification(withIdentifier: String) -> RobinNotification?.
let scheduledNotification = Robin.scheduler.notification(withIdentifier: "identifier")To cancel a notification, either call cancel(notification: RobinNotification) or cancel(withIdentifier: String)
Robin.scheduler.cancel(notification: scheduledNotification)Robin.scheduler.cancel(withIdentifier: scheduledNotification.identifier)Robin allows you to cancel all scheduled notifications by calling cancelAll()
Robin.scheduler.cancelAll()Robin utilizes the threadIdentifier property to manage multiple notifications as a group under the same identifier. To group multiple notifications under the same identifier, you can either set threadIdentifier of the notification to the same string or schedule a notification group by calling schedule(group: RobinNotificationGroup):
let notifications = ... // an array of `RobinNotification`
let group = RobinNotificationGroup(notifications: notifications)
// or
let group = RobinNotificationGroup(notifications: notifications, identifier: "group_identifier")
let scheduledGroup = Robin.scheduler.schedule(group: group)Robin will automatically set threadIdentifier of each RobinNotification in the array to the group's identifier. If you omit identifier when initializing the group, Robin will create a unique identifier.
Simply retrieve a scheduled notification group by calling group(withIdentifier: String) -> RobinNotificationGroup?.
let scheduledGroup = Robin.scheduler.group(withIdentifier: "group_identifier")Robin will return a group if there exists at least one notification with threadIdentifier the same as the group's identifier. The returned group might contain less notifications than initially scheduled since some of them might have already been delivered by the system.
To cancel a notification group, either call cancel(group: RobinNotificationGroup) or cancel(groupWithIdentifier: String)
Robin.scheduler.cancel(group: group)Robin.scheduler.cancel(groupWithIdentifer: group.identifer)To retrieve all delivered notifications that are displayed in the notification center, call allDelivered(completionHandler: @escaping ([RobinNotification]) -> Void).
Robin.manager.allDelivered { deliveredNotifications in
// Access delivered notifications
}To remove a delivered notification from the notification center, either call removeDelivered(notification: RobinNotification) or removeDelivered(withIdentifier identifier: String).
Robin.manager.removeDelivered(notification: deliveredNotification)Robin.manager.removeDelivered(withIdentifier: deliveredNotification.identifier)Robin allows you to remove all delivered notifications by calling removeAllDelivered()
Robin.manager.removeAllDelivered()Robin is preset to allow 60 notifications to be scheduled by the system. The remaining four slots are kept for the app-defined notifications. These free slots are currently not handled by Robin; if you use Robin to utilize these slots, the notifications will be discarded. To change the maximum allowed, just update Robin.maximumAllowedNotifications.
Ahmed Mohamed, [email protected]
Robin is available under the MIT license. See the LICENSE file for more info.