├── .gitignore ├── CHANGELOG.md ├── Classes ├── MMPReactiveNotification.h └── MMPReactiveNotification.m ├── LICENSE ├── MMPReactiveNotification.podspec └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | # Xcode 2 | # 3 | build/ 4 | *.pbxuser 5 | !default.pbxuser 6 | *.mode1v3 7 | !default.mode1v3 8 | *.mode2v3 9 | !default.mode2v3 10 | *.perspectivev3 11 | !default.perspectivev3 12 | xcuserdata 13 | *.xccheckout 14 | *.moved-aside 15 | DerivedData 16 | *.hmap 17 | *.ipa 18 | *.xcuserstate 19 | 20 | # CocoaPods 21 | # 22 | # We recommend against adding the Pods directory to your .gitignore. However 23 | # you should judge for yourself, the pros and cons are mentioned at: 24 | # http://guides.cocoapods.org/using/using-cocoapods.html#should-i-ignore-the-pods-directory-in-source-control 25 | # 26 | Pods/ 27 | Podfile.lock 28 | 29 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # MMPReactiveNotification CHANGELOG 2 | 3 | ## 0.4.1 4 | 5 | * Fixes #5 (Crash on 7, unrecognized selector: registerUserNotificationSettings) 6 | 7 | ## 0.4.0 8 | 9 | * `MMPLocalNotificationSpec` for specifying and scheduling local notification. 10 | 11 | ## 0.3.2 12 | 13 | * Add `remoteNotificationsOnLaunch`. 14 | 15 | ## 0.3.1 16 | 17 | * Individual category setting. 18 | * More flexibility on scheduling local notifications. 19 | * Signal for local notifications filtered by action. 20 | * Signal for local notifications on app launches. 21 | 22 | ## 0.3.0 23 | 24 | * Local notification signal & scheduling. 25 | * Notification settings registration signal. 26 | 27 | ## 0.2.0 28 | 29 | * Replace singleton with settable service. 30 | * Settings for remote registration. 31 | 32 | ## 0.1.0 33 | 34 | * Remote registration signal 35 | * Remote push notification signal 36 | -------------------------------------------------------------------------------- /Classes/MMPReactiveNotification.h: -------------------------------------------------------------------------------- 1 | // 2 | // MMPReactiveNotification.h 3 | // 4 | // The MIT License (MIT) 5 | // Copyright (c) 2015 Mamad Purbo, purbo.org 6 | // 7 | // Permission is hereby granted, free of charge, to any person obtaining a copy 8 | // of this software and associated documentation files (the "Software"), to deal 9 | // in the Software without restriction, including without limitation the rights 10 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | // copies of the Software, and to permit persons to whom the Software is 12 | // furnished to do so, subject to the following conditions: 13 | // 14 | // The above copyright notice and this permission notice shall be included in 15 | // all copies or substantial portions of the Software. 16 | // 17 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 23 | // THE SOFTWARE. 24 | // 25 | #import 26 | #import 27 | 28 | @interface MMPLocalNotificationSpec : NSObject 29 | 30 | - (id)initWithNotification:(UILocalNotification *)notification; 31 | 32 | // Composing 33 | - (instancetype)withAlertBody:(NSString *)alertBody; 34 | - (instancetype)withAlertAction:(NSString *)alertAction; 35 | - (instancetype)withAlertTitle:(NSString *)alertTitle; 36 | - (instancetype)withAlertLaunchImage:(NSString *)alertLaunchImage; 37 | - (instancetype)withCategory:(NSString *)category; 38 | - (instancetype)hasAction:(BOOL)hasAction; 39 | 40 | // Other configurations 41 | - (instancetype)withApplicationIconBadgeNumber:(NSInteger)applicationIconBadgeNumber; 42 | - (instancetype)withSoundName:(NSString *)soundName; 43 | - (instancetype)withUserInfo:(NSDictionary *)userInfo; 44 | 45 | // Scheduling 46 | - (instancetype)timeZone:(NSTimeZone *)timeZone; 47 | - (instancetype)fireAt:(NSDate *)date; 48 | - (instancetype)fireDailyAtHour:(NSInteger)hour minute:(NSInteger)minute second:(NSInteger)second; 49 | 50 | - (void)schedule; 51 | 52 | @end 53 | 54 | @interface MMPReactiveNotification : NSObject 55 | 56 | + (instancetype)service; 57 | 58 | // ============================================================================= 59 | // Settings 60 | // ============================================================================= 61 | 62 | #if __IPHONE_OS_VERSION_MAX_ALLOWED >= 80000 63 | - (instancetype)notificationTypes:(UIUserNotificationType)types; 64 | - (instancetype)category:(UIMutableUserNotificationCategory *)category; 65 | - (instancetype)categories:(NSSet *)categories; 66 | #else 67 | - (instancetype)notificationTypes:(UIRemoteNotificationType)types; 68 | #endif 69 | 70 | // ============================================================================= 71 | // Settings 72 | // ============================================================================= 73 | 74 | /** 75 | * Register for remote notification based. Returned signal produces remote 76 | * notification token. 77 | * 78 | * @return Signal producing remote notification token as NSData. 79 | */ 80 | - (RACSignal *)remoteRegistration; 81 | 82 | /** 83 | * Returns a signal that will produces an NSDictionary every time the app 84 | * receives remote push notification. 85 | * 86 | * @return Signal producing NSDictionary push data. 87 | */ 88 | - (RACSignal *)remoteNotifications; 89 | 90 | /** 91 | * Returns a signal that will produces an UILocalNotification every time the 92 | * app receives local notification. 93 | * 94 | * @return Signal producing UILocalNotification. 95 | */ 96 | - (RACSignal *)localNotifications; 97 | - (RACSignal *)localNotificationsWithActionIdentifier:(NSString *)actionIdentifier; 98 | - (RACSignal *)localNotificationsOnLaunch; 99 | 100 | - (RACSignal *)remoteNotificationsOnLaunch; 101 | 102 | - (RACSignal *)userNotificationSettingsRegistration; 103 | 104 | /** 105 | * Simple wrapper of UIApplication's scheduleLocalNotification: 106 | * 107 | * @param notification local notification to be scheduled. 108 | */ 109 | - (void)scheduleLocalNotification:(UILocalNotification *)notification; 110 | /* 111 | - (void)scheduleLocalNotificationWithAlert:(NSString *)alertBody toBeFiredAt:(NSDate *)fireDate; 112 | - (void)scheduleLocalNotificationWithAlert:(NSString *)alertBody 113 | withUserInfo:(NSDictionary *)userInfo 114 | toBeFiredAt:(NSDate *)fireDate; 115 | - (void)scheduleLocalNotificationWithAlert:(NSString *)alertBody 116 | withSound:(NSString *)soundName 117 | withUserInfo:(NSDictionary *)userInfo 118 | withCategory:(NSString *)category 119 | toBeFiredAt:(NSDate *)fireDate; 120 | - (void)scheduleDailyLocalNotificationWithAlert:(NSString *)alertBody 121 | withSound:(NSString *)soundName 122 | withUserInfo:(NSDictionary *)userInfo 123 | withCategory:(NSString *)category 124 | withIconBadgeNumber:(NSInteger)applicationIconBadgeNumber 125 | toBeFiredAtHour:(NSInteger)hour minute:(NSInteger)minute second:(NSInteger)second 126 | inTimeZone:(NSTimeZone *)timeZone; 127 | */ 128 | 129 | @end 130 | -------------------------------------------------------------------------------- /Classes/MMPReactiveNotification.m: -------------------------------------------------------------------------------- 1 | // 2 | // MMPReactiveNotification.m 3 | // 4 | // The MIT License (MIT) 5 | // Copyright (c) 2015 Mamad Purbo, purbo.org 6 | // 7 | 8 | #import "MMPReactiveNotification.h" 9 | 10 | #ifdef DEBUG 11 | # define MMPRxN_LOG(fmt, ...) NSLog((@"%s [Line %d] " fmt), __PRETTY_FUNCTION__, __LINE__, ##__VA_ARGS__); 12 | #else 13 | # define MMPRxN_LOG(...) 14 | #endif 15 | 16 | @interface MMPLocalNotificationSpec() 17 | 18 | @property (nonatomic, strong) UILocalNotification *localNotification; 19 | 20 | @end 21 | 22 | @implementation MMPLocalNotificationSpec 23 | 24 | - (id)init { 25 | if (self = [super init]) { 26 | self.localNotification = [UILocalNotification new]; 27 | } 28 | return self; 29 | } 30 | 31 | - (id)initWithNotification:(UILocalNotification *)notification { 32 | if (self = [super init]) { 33 | self.localNotification = notification; 34 | } 35 | return self; 36 | } 37 | 38 | - (instancetype)withAlertBody:(NSString *)alertBody { 39 | _localNotification.alertBody = alertBody; 40 | return self; 41 | } 42 | 43 | - (instancetype)withAlertAction:(NSString *)alertAction { 44 | _localNotification.alertAction = alertAction; 45 | return self; 46 | } 47 | 48 | - (instancetype)withAlertTitle:(NSString *)alertTitle { 49 | _localNotification.alertTitle = alertTitle; 50 | return self; 51 | } 52 | 53 | - (instancetype)withAlertLaunchImage:(NSString *)alertLaunchImage { 54 | _localNotification.alertLaunchImage = alertLaunchImage; 55 | return self; 56 | } 57 | 58 | - (instancetype)withCategory:(NSString *)category { 59 | _localNotification.category = category; 60 | return self; 61 | } 62 | 63 | - (instancetype)hasAction:(BOOL)hasAction { 64 | _localNotification.hasAction = hasAction; 65 | return self; 66 | } 67 | 68 | - (instancetype)withApplicationIconBadgeNumber:(NSInteger)applicationIconBadgeNumber { 69 | _localNotification.applicationIconBadgeNumber = applicationIconBadgeNumber; 70 | return self; 71 | } 72 | 73 | - (instancetype)withSoundName:(NSString *)soundName { 74 | _localNotification.soundName = soundName; 75 | return self; 76 | } 77 | 78 | - (instancetype)withUserInfo:(NSDictionary *)userInfo { 79 | _localNotification.userInfo = userInfo; 80 | return self; 81 | } 82 | 83 | - (instancetype)fireAt:(NSDate *)date { 84 | _localNotification.fireDate = date; 85 | return self; 86 | } 87 | 88 | - (instancetype)fireDailyAtHour:(NSInteger)hour minute:(NSInteger)minute second:(NSInteger)second { 89 | #if __IPHONE_OS_VERSION_MAX_ALLOWED >= 80000 90 | NSCalendar *gregorian = [NSCalendar calendarWithIdentifier:NSCalendarIdentifierGregorian]; 91 | NSDateComponents *components = [gregorian components:(NSCalendarUnitHour|NSCalendarUnitMinute|NSCalendarUnitSecond) fromDate:[NSDate new]]; 92 | #else 93 | NSCalendar *gregorian = [NSCalendar calendarWithIdentifier:NSGregorianCalendar]; 94 | NSDateComponents *components = [gregorian components:(NSHourCalendarUnit|NSMinuteCalendarUnit|NSSecondCalendarUnit) fromDate:[NSDate new]]; 95 | #endif 96 | if (_localNotification.timeZone != nil) { 97 | gregorian.timeZone = _localNotification.timeZone; 98 | } 99 | 100 | [components setHour:-[components hour] + hour]; 101 | [components setMinute:-[components minute] + minute]; 102 | [components setSecond:-[components second] + second]; 103 | 104 | #if __IPHONE_OS_VERSION_MAX_ALLOWED >= 80000 105 | _localNotification.repeatInterval = NSCalendarUnitDay; 106 | #else 107 | _localNotification.repeatInterval = NSDayCalendarUnit; 108 | #endif 109 | return [self fireAt:[gregorian dateByAddingComponents:components toDate:[NSDate new] options:0]]; 110 | } 111 | 112 | - (instancetype)timeZone:(NSTimeZone *)timeZone { 113 | _localNotification.timeZone = timeZone; 114 | return self; 115 | } 116 | 117 | - (void)schedule { 118 | [[MMPReactiveNotification service] scheduleLocalNotification:_localNotification]; 119 | } 120 | 121 | @end 122 | 123 | 124 | @interface MMPReactiveNotification() 125 | 126 | @property (nonatomic, assign) UIResponder *delegate; 127 | 128 | #if __IPHONE_OS_VERSION_MAX_ALLOWED >= 80000 129 | @property (nonatomic, assign) UIUserNotificationType types; 130 | @property (nonatomic, copy) NSSet *categories; 131 | #else 132 | @property (nonatomic, assign) UIRemoteNotificationType types; 133 | #endif 134 | 135 | @end 136 | 137 | @implementation MMPReactiveNotification 138 | 139 | - (id)init { 140 | if (self = [super init]) { 141 | [self defaultSettings]; 142 | 143 | UIApplication *app = [UIApplication sharedApplication]; 144 | self.delegate = app.delegate; 145 | } 146 | return self; 147 | } 148 | 149 | - (void)defaultSettings { 150 | #if __IPHONE_OS_VERSION_MAX_ALLOWED >= 80000 151 | self.types = UIUserNotificationTypeAlert | UIUserNotificationTypeBadge | UIUserNotificationTypeSound; 152 | self.categories = nil; 153 | #else 154 | self.types = UIRemoteNotificationTypeBadge | UIRemoteNotificationTypeSound | UIRemoteNotificationTypeAlert; 155 | #endif 156 | } 157 | 158 | + (instancetype)service { 159 | return [MMPReactiveNotification new]; 160 | } 161 | 162 | #if __IPHONE_OS_VERSION_MAX_ALLOWED >= 80000 163 | 164 | - (instancetype)notificationTypes:(UIUserNotificationType)types { 165 | self.types = types; 166 | return self; 167 | } 168 | 169 | - (instancetype)category:(UIMutableUserNotificationCategory *)category { 170 | if (!self.categories) { 171 | self.categories = [NSMutableSet setWithObject:category]; 172 | } else { 173 | if ([_categories isKindOfClass:[NSMutableSet class]]) { 174 | [(NSMutableSet *)_categories addObject:category]; 175 | } 176 | } 177 | return self; 178 | } 179 | 180 | - (instancetype)categories:(NSSet *)categories { 181 | self.categories = categories; 182 | return self; 183 | } 184 | 185 | - (BOOL)notificationTypesUpToDate { 186 | UIUserNotificationSettings *settings = [[UIApplication sharedApplication] currentUserNotificationSettings]; 187 | return settings.types == self.types; 188 | } 189 | 190 | #else 191 | 192 | - (instancetype)notificationTypes:(UIRemoteNotificationType)types { 193 | self.types = types; 194 | return self; 195 | } 196 | 197 | #endif 198 | 199 | - (RACSignal *)remoteRegistration { 200 | return [RACSignal createSignal:^RACDisposable *(id subscriber) { 201 | 202 | RACSignal *reg = [[self.delegate rac_signalForSelector:@selector(application:didRegisterForRemoteNotificationsWithDeviceToken:) 203 | fromProtocol:@protocol(UIApplicationDelegate)] 204 | reduceEach:^id(id _, NSData *deviceToken) { 205 | return deviceToken; 206 | }]; 207 | RACSignal *err = [[self.delegate rac_signalForSelector:@selector(application:didFailToRegisterForRemoteNotificationsWithError:) 208 | fromProtocol:@protocol(UIApplicationDelegate)] 209 | reduceEach:^id(id _, NSError *error) { 210 | return error; 211 | }]; 212 | 213 | [reg subscribeNext:^(NSData *deviceToken) { 214 | [subscriber sendNext:deviceToken]; 215 | [subscriber sendCompleted]; 216 | }]; 217 | 218 | [err subscribeNext:^(NSError *error) { 219 | [subscriber sendError:error]; 220 | }]; 221 | 222 | MMPRxN_LOG(@"Registering for push.") 223 | 224 | UIApplication *app = [UIApplication sharedApplication]; 225 | 226 | #if __IPHONE_OS_VERSION_MAX_ALLOWED >= 80000 227 | if ([app respondsToSelector:@selector(registerUserNotificationSettings:)]) { 228 | [app registerUserNotificationSettings:[UIUserNotificationSettings settingsForTypes:self.types 229 | categories:self.categories]]; 230 | [app registerForRemoteNotifications]; 231 | } else { 232 | [app registerForRemoteNotificationTypes:self.types]; 233 | } 234 | #else 235 | [app registerForRemoteNotificationTypes:self.types]; 236 | #endif 237 | 238 | return [RACDisposable disposableWithBlock:^{ 239 | MMPRxN_LOG(@"Disposing subscriber for push registration.") 240 | }]; 241 | 242 | }]; 243 | } 244 | 245 | - (RACSignal *)userNotificationSettingsRegistration { 246 | return [[self.delegate rac_signalForSelector:@selector(application:didRegisterUserNotificationSettings:) 247 | fromProtocol:@protocol(UIApplicationDelegate)] 248 | reduceEach:^id(id _, UIUserNotificationSettings *notificationSettings) { 249 | return notificationSettings; 250 | }]; 251 | } 252 | 253 | - (RACSignal *)remoteNotifications { 254 | return [[self.delegate rac_signalForSelector:@selector(application:didReceiveRemoteNotification:) 255 | fromProtocol:@protocol(UIApplicationDelegate)] 256 | reduceEach:^id(id _, NSDictionary *userInfo) { 257 | return userInfo; 258 | }]; 259 | } 260 | 261 | - (RACSignal *)localNotifications { 262 | return [[self.delegate rac_signalForSelector:@selector(application:didReceiveLocalNotification:) 263 | fromProtocol:@protocol(UIApplicationDelegate)] 264 | reduceEach:^id(id _, UILocalNotification *notification) { 265 | return notification; 266 | }]; 267 | } 268 | 269 | - (RACSignal *)localNotificationsWithActionIdentifier:(NSString *)actionIdentifier { 270 | return [[[self.delegate rac_signalForSelector:@selector(application:handleActionWithIdentifier:forLocalNotification:completionHandler:) 271 | fromProtocol:@protocol(UIApplicationDelegate)] 272 | filter:^BOOL(RACTuple *tuple) { 273 | NSString *comingIdentifier = tuple.second; 274 | MMPRxN_LOG(@"Filtering coming action with identifier: %@, expecting identifier: %@", comingIdentifier, actionIdentifier) 275 | return (actionIdentifier == nil || [actionIdentifier isEqualToString:comingIdentifier]); 276 | }] 277 | reduceEach:^id(id _, id identifier, UILocalNotification *notification, id completionHandler) { 278 | return notification; 279 | }]; 280 | } 281 | 282 | - (RACSignal *)localNotificationsOnLaunch { 283 | return [[[self.delegate rac_signalForSelector:@selector(application:didFinishLaunchingWithOptions:) 284 | fromProtocol:@protocol(UIApplicationDelegate)] 285 | filter:^BOOL(RACTuple *tuple) { 286 | NSDictionary *launchOptions = tuple.second; 287 | MMPRxN_LOG(@"Filtering application launch with options: %@, expecting local notification", launchOptions) 288 | return (launchOptions && [launchOptions objectForKey:UIApplicationLaunchOptionsLocalNotificationKey]); 289 | }] 290 | reduceEach:^id(id _, NSDictionary *launchOptions) { 291 | return [launchOptions objectForKey:UIApplicationLaunchOptionsLocalNotificationKey]; 292 | }]; 293 | } 294 | 295 | - (RACSignal *)remoteNotificationsOnLaunch { 296 | return [[[self.delegate rac_signalForSelector:@selector(application:didFinishLaunchingWithOptions:) 297 | fromProtocol:@protocol(UIApplicationDelegate)] 298 | filter:^BOOL(RACTuple *tuple) { 299 | NSDictionary *launchOptions = tuple.second; 300 | MMPRxN_LOG(@"Filtering application launch with options: %@, expecting remote notification", launchOptions) 301 | return (launchOptions && [launchOptions objectForKey:UIApplicationLaunchOptionsRemoteNotificationKey]); 302 | }] 303 | reduceEach:^id(id _, NSDictionary *launchOptions) { 304 | return [launchOptions objectForKey:UIApplicationLaunchOptionsRemoteNotificationKey]; 305 | }]; 306 | } 307 | 308 | - (void)scheduleLocalNotification:(UILocalNotification *)notification { 309 | #if __IPHONE_OS_VERSION_MAX_ALLOWED >= 80000 310 | if (![self notificationTypesUpToDate]) { 311 | MMPRxN_LOG(@"Settings are not up-to-date, register settings before scheduling.") 312 | [[[self userNotificationSettingsRegistration] 313 | take:1] 314 | subscribeNext:^(UIUserNotificationSettings *notificationSettings) { 315 | MMPRxN_LOG(@"Settings registered with types = %lu, now scheduling notification.", (unsigned long)notificationSettings.types) 316 | [[UIApplication sharedApplication] scheduleLocalNotification:notification]; 317 | }]; 318 | [[UIApplication sharedApplication] registerUserNotificationSettings:[UIUserNotificationSettings settingsForTypes:self.types 319 | categories:self.categories]]; 320 | } else { 321 | MMPRxN_LOG(@"Schedule notification immediately, settings are up-to-date.") 322 | [[UIApplication sharedApplication] scheduleLocalNotification:notification]; 323 | } 324 | #else 325 | [[UIApplication sharedApplication] scheduleLocalNotification:notification]; 326 | #endif 327 | } 328 | 329 | @end 330 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 Mamad Purbo 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /MMPReactiveNotification.podspec: -------------------------------------------------------------------------------- 1 | Pod::Spec.new do |s| 2 | s.name = "MMPReactiveNotification" 3 | s.version = "0.4.1" 4 | s.summary = "Local and remote push notifications as reactive signals with ReactiveCocoa" 5 | s.description = <<-DESC 6 | MMPReactiveNotification is a reactive library providing signals for local and remote push notifications. 7 | 8 | Features: 9 | * No more notification related delegate methods, registration and notifications are available as signals. 10 | * Signal for remote push registration. 11 | * Signal for receiving remote notifications. 12 | * Signal for receiving local notifications. 13 | * Signal for notification settings registration. 14 | * Local notification scheduling. 15 | DESC 16 | s.homepage = "https://github.com/mpurbo/MMPReactiveNotification" 17 | s.license = 'MIT' 18 | s.author = { "Mamad Purbo" => "m.purbo@gmail.com" } 19 | s.source = { :git => "https://github.com/mpurbo/MMPReactiveNotification.git", :tag => s.version.to_s } 20 | s.social_media_url = 'https://twitter.com/purubo' 21 | 22 | s.platform = :ios 23 | s.ios.deployment_target = '7.0' 24 | s.source_files = 'Classes' 25 | s.dependency 'ReactiveCocoa' 26 | s.requires_arc = true 27 | end 28 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # MMPReactiveNotification 2 | 3 | MMPReactiveNotification is a reactive library providing signals for local and remote push notifications. 4 | 5 | Features: 6 | * No more notification related delegate methods, registration and notifications are available as signals. 7 | * Signal for remote push registration. 8 | * Signal for receiving remote notifications. 9 | * Signal for receiving local notifications. 10 | * Signal for notification settings registration. 11 | * Local notification scheduling. 12 | 13 | ## Installation 14 | 15 | MMPReactiveNotification is available through [CocoaPods](http://cocoapods.org), to install 16 | it simply add the following line to your Podfile: 17 | ``` 18 | pod 'MMPReactiveNotification' 19 | ``` 20 | 21 | ## Usage 22 | 23 | Use `MMPReactiveNotification` class method `service` anywhere in your application to subscribe to an appropriate signal. For example, following example shows how to use `remoteRegistration` signal to register for remote push notification with [default settings](#custom-settings) and receive the push token: 24 | ```objc 25 | // import the header 26 | #import 27 | 28 | [[[MMPReactiveNotification service] 29 | remoteRegistration] 30 | subscribeNext:^(NSData *tokenData) { 31 | NSLog(@"Receiving push token: %@", tokenData); 32 | // Send the push token to your server 33 | } 34 | error:^(NSError *error) { 35 | NSLog(@"Push registration error: %@", error); 36 | }]; 37 | 38 | ``` 39 | 40 | To receive remote push notifications, use `remoteNotifications` method: 41 | ```objc 42 | [[[MMPReactiveNotification service] 43 | remoteNotifications] 44 | subscribeNext:^(NSDictionary *pushData) { 45 | NSLog(@"Receiving push: %@", pushData); 46 | }]; 47 | ``` 48 | 49 | To receive local notifications, use `localNotifications` method: 50 | ```objc 51 | [[[MMPReactiveNotification service] 52 | localNotifications] 53 | subscribeNext:^(UILocalNotification *localNotification) { 54 | NSLog(@"Receiving local notification: %@", localNotification.alertBody); 55 | }]; 56 | ``` 57 | 58 | ## Custom Settings 59 | 60 | Default settings for remote push registration are: 61 | - Enable alert, badge, and sound (see [UIUserNotificationType](https://developer.apple.com/library/prerelease/ios/documentation/UIKit/Reference/UIUserNotificationSettings_class/index.html#//apple_ref/c/tdef/UIUserNotificationType)). 62 | - No custom actions (see [UIUserNotificationCategory](https://developer.apple.com/library/prerelease/ios/documentation/UIKit/Reference/UIUserNotificationCategory_class/index.html#//apple_ref/occ/cl/UIUserNotificationCategory)). 63 | 64 | To customize these settings, use `notificationTypes` and `categories` methods as shown in the following example: 65 | ```objc 66 | // only enable alert and badge 67 | [[[[MMPReactiveNotification service] 68 | notificationTypes:UIUserNotificationTypeAlert|UIUserNotificationTypeBadge] 69 | remoteRegistration] 70 | subscribeNext:^(NSData *tokenData) { 71 | NSLog(@"Receiving push token: %@", tokenData); 72 | // Send the push token to your server 73 | }]; 74 | ``` 75 | 76 | ## Scheduling Local Notifications 77 | 78 | To create a local notification, use a new `MMPLocalNotificationSpec` to first specify the notification, then call `schedule` method to schedule it: 79 | ```objc 80 | [[[[[[MMPLocalNotificationSpec new] 81 | withAlertBody:@"Your daily quiz is now available!"] 82 | withSoundName:UILocalNotificationDefaultSoundName] withCategory:@"Quiz"] 83 | fireDailyAtHour:18 minute:0 second:0] 84 | schedule]; 85 | ``` 86 | This scheduling will also automatically register notification settings if it hasn't been done previously. 87 | 88 | ## Contact 89 | 90 | MMPReactiveNotification is maintained by [Mamad Purbo](https://twitter.com/purubo) 91 | 92 | ## License 93 | 94 | MMPReactiveNotification is available under the MIT license. See the LICENSE file for more info. 95 | --------------------------------------------------------------------------------