Przeglądaj źródła

WIP enhanced iOS10 support

Sebastián Katzer 9 lat temu
rodzic
commit
fdf8470de3

+ 22 - 16
plugin.xml

@@ -3,7 +3,7 @@
 <plugin xmlns="http://apache.org/cordova/ns/plugins/1.0"
         xmlns:android="http://schemas.android.com/apk/res/android"
         id="de.appplant.cordova.plugin.local-notification"
-        version="0.8.4">
+        version="0.8.5-dev">
 
     <name>LocalNotification</name>
 
@@ -11,7 +11,7 @@
 
     <repo>https://github.com/katzer/cordova-plugin-local-notifications.git</repo>
 
-    <keywords>appplant, notification, local notification</keywords>
+    <keywords>appplant, notification, local notification, user notification</keywords>
 
     <license>Apache 2.0</license>
 
@@ -20,23 +20,15 @@
     <!-- cordova -->
     <engines>
         <engine name="cordova" version=">=3.6.0" />
-        <!-- TODO next version: Probably I meant cordova-lib -->
-        <!-- <engine name="cordova-plugman" version=">=4.3.0" /> -->
+        <engine name="cordova-plugman" version=">=4.3.0" />
         <engine name="cordova-windows" version=">=4.2.0" />
+        <engine name="apple-ios" version=">=10.0.0" />
     </engines>
 
     <!-- dependencies -->
     <dependency id="cordova-plugin-device" />
     <dependency id="cordova-plugin-app-event" />
 
-    <!-- info -->
-    <info>
-        Your support is needed. If you use the local-notification plugin please support us in order to ensure further development.
-        https://github.com/katzer/cordova-plugin-local-notifications#supporting
-
-        Thank you!
-    </info>
-
     <!-- js -->
     <js-module src="www/local-notification.js" name="LocalNotification">
         <clobbers target="cordova.plugins.notification.local" />
@@ -63,17 +55,31 @@
             </feature>
         </config-file>
 
+        <framework src="UserNotifications.framework" />
+
         <header-file src="src/ios/APPLocalNotification.h" />
         <source-file src="src/ios/APPLocalNotification.m" />
 
         <header-file src="src/ios/APPLocalNotificationOptions.h" />
         <source-file src="src/ios/APPLocalNotificationOptions.m" />
 
-        <header-file src="src/ios/UIApplication+APPLocalNotification.h" />
-        <source-file src="src/ios/UIApplication+APPLocalNotification.m" />
+        <header-file src="src/ios/UNUserNotificationCenter+APPLocalNotification.h" />
+        <source-file src="src/ios/UNUserNotificationCenter+APPLocalNotification.m" />
+
+        <header-file src="src/ios/UNMutableNotificationContent+APPLocalNotification.h" />
+        <source-file src="src/ios/UNMutableNotificationContent+APPLocalNotification.m" />
+
+        <header-file src="src/ios/UNNotificationRequest+APPLocalNotification.h" />
+        <source-file src="src/ios/UNNotificationRequest+APPLocalNotification.m" />
+
+        <header-file src="src/ios9/APPLocalNotificationOptions.ios9.h" />
+        <source-file src="src/ios9/APPLocalNotificationOptions.ios9.m" />
+
+        <header-file src="src/ios9/UIApplication+APPLocalNotification.ios9.h" />
+        <source-file src="src/ios9/UIApplication+APPLocalNotification.ios9.m" />
 
-        <header-file src="src/ios/UILocalNotification+APPLocalNotification.h" />
-        <source-file src="src/ios/UILocalNotification+APPLocalNotification.m" />
+        <header-file src="src/ios9/UILocalNotification+APPLocalNotification.ios9.h" />
+        <source-file src="src/ios9/UILocalNotification+APPLocalNotification.ios9.m" />
 
     </platform>
 

+ 3 - 1
src/ios/APPLocalNotification.h

@@ -24,7 +24,9 @@
 #import <Foundation/Foundation.h>
 #import <Cordova/CDVPlugin.h>
 
-@interface APPLocalNotification : CDVPlugin
+@import UserNotifications;
+
+@interface APPLocalNotification : CDVPlugin <UNUserNotificationCenterDelegate>
 
 // Execute all queued events
 - (void) deviceready:(CDVInvokedUrlCommand*)command;

+ 406 - 212
src/ios/APPLocalNotification.m

@@ -23,20 +23,28 @@
 
 #import "APPLocalNotification.h"
 #import "APPLocalNotificationOptions.h"
-#import "UIApplication+APPLocalNotification.h"
-#import "UILocalNotification+APPLocalNotification.h"
+#import "UNUserNotificationCenter+APPLocalNotification.h"
+#import "UNNotificationRequest+APPLocalNotification.h"
+#import "UNMutableNotificationContent+APPLocalNotification.h"
 
- @import UserNotifications;
+#import "APPLocalNotificationOptions.ios9.h"
+#import "UIApplication+APPLocalNotification.ios9.h"
+#import "UILocalNotification+APPLocalNotification.ios9.h"
+
+#define SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(v)  ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] != NSOrderedAscending)
 
 @interface APPLocalNotification ()
 
-// Retrieves the application state
-@property (readonly, getter=applicationState) NSString* applicationState;
+// Property reader for [self app]
+@property (readonly, getter=app) UIApplication* app;
+// Property reader for [self center]
+@property (readonly, getter=center) UNUserNotificationCenter* center;
 // All events will be queued until deviceready has been fired
 @property (readwrite, assign) BOOL deviceready;
 // Event queue
 @property (readonly, nonatomic, retain) NSMutableArray* eventQueue;
-// Needed when calling `registerPermission`
+
+// IOS9: TODO remove later
 @property (nonatomic, retain) CDVInvokedUrlCommand* command;
 
 @end
@@ -73,24 +81,34 @@
     NSArray* notifications = command.arguments;
 
     [self.commandDelegate runInBackground:^{
-        for (NSDictionary* options in notifications) {
-            UILocalNotification* notification;
+        if (SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"10.0")) {
+            for (NSDictionary* options in notifications) {
+                UNMutableNotificationContent* notification;
+
+                notification = [[UNMutableNotificationContent alloc]
+                                initWithOptions:options];
 
-            notification = [[UILocalNotification alloc]
-                            initWithOptions:options];
-            notification.timeZone = [NSTimeZone defaultTimeZone];
-            notification.repeatInterval = 0;
+                [self scheduleNotification:notification];
+                //[self fireEvent:@"add" notification:notification];
+            }
+        } else {
+            for (NSDictionary* options in notifications) {
+                UILocalNotification* notification;
 
-            [self scheduleLocalNotification:[notification copy]];
-            [self fireEvent:@"schedule" notification:notification];
+                notification = [[UILocalNotification alloc]
+                                initWithOptions:options];
 
-            if (notifications.count > 1) {
-                [NSThread sleepForTimeInterval:0.01];
+                [self scheduleLocalNotification:[notification copy]];
+                [self fireEvent:@"schedule" localnotification:notification];
+
+                if (notifications.count > 1) {
+                    [NSThread sleepForTimeInterval:0.01];
+                }
             }
         }
 
         [self execCallback:command];
-    }];
+     }];
 }
 
 /**
@@ -104,22 +122,43 @@
     NSArray* notifications = command.arguments;
 
     [self.commandDelegate runInBackground:^{
-        for (NSDictionary* options in notifications) {
-            NSNumber* id = [options objectForKey:@"id"];
-            UILocalNotification* notification;
+        if (SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"10.0")) {
+            for (NSDictionary* options in notifications) {
+                NSNumber* id = [options objectForKey:@"id"];
+                UNNotificationRequest* notification;
+
+                notification = [self.center getNotificationWithId:id];
+
+                if (!notification)
+                    continue;
+
+                //            [self updateNotification:[notification copy]
+                //                         withOptions:options];
+                //
+                //            [self fireEvent:@"update" notification:notification];
+                //
+                //            if (notifications.count > 1) {
+                //                [NSThread sleepForTimeInterval:0.01];
+                //            }
+            }
+        } else {
+            for (NSDictionary* options in notifications) {
+                NSNumber* id = [options objectForKey:@"id"];
+                UILocalNotification* notification;
 
-            notification = [self.app localNotificationWithId:id];
+                notification = [self.app localNotificationWithId:id];
 
-            if (!notification)
-                continue;
+                if (!notification)
+                    continue;
 
-            [self updateLocalNotification:[notification copy]
-                              withOptions:options];
+                [self updateLocalNotification:[notification copy]
+                                  withOptions:options];
 
-            [self fireEvent:@"update" notification:notification];
+                [self fireEvent:@"update" localnotification:notification];
 
-            if (notifications.count > 1) {
-                [NSThread sleepForTimeInterval:0.01];
+                if (notifications.count > 1) {
+                    [NSThread sleepForTimeInterval:0.01];
+                }
             }
         }
 
@@ -136,16 +175,30 @@
 - (void) cancel:(CDVInvokedUrlCommand*)command
 {
     [self.commandDelegate runInBackground:^{
-        for (NSNumber* id in command.arguments) {
-            UILocalNotification* notification;
+        if (SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"10.0")) {
+            for (NSNumber* id in command.arguments) {
+                UNNotificationRequest* notification;
 
-            notification = [self.app localNotificationWithId:id];
+                notification = [self.center getNotificationWithId:id];
 
-            if (!notification)
-                continue;
+                if (!notification)
+                    continue;
 
-            [self.app cancelLocalNotification:notification];
-            [self fireEvent:@"cancel" notification:notification];
+                [self.center cancelNotification:notification];
+                [self fireEvent:@"cancel" notification:notification];
+            }
+        } else {
+            for (NSNumber* id in command.arguments) {
+                UILocalNotification* notification;
+
+                notification = [self.app localNotificationWithId:id];
+
+                if (!notification)
+                    continue;
+
+                [self.app cancelLocalNotification:notification];
+                [self fireEvent:@"cancel" localnotification:notification];
+            }
         }
 
         [self execCallback:command];
@@ -158,7 +211,7 @@
 - (void) cancelAll:(CDVInvokedUrlCommand*)command
 {
     [self.commandDelegate runInBackground:^{
-        [self cancelAllLocalNotifications];
+        [self cancelAllNotifications];
         [self fireEvent:@"cancelall"];
         [self execCallback:command];
     }];
@@ -173,16 +226,30 @@
 - (void) clear:(CDVInvokedUrlCommand*)command
 {
     [self.commandDelegate runInBackground:^{
-        for (NSNumber* id in command.arguments) {
-            UILocalNotification* notification;
+        if (SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"10.0")) {
+            for (NSNumber* id in command.arguments) {
+                UNNotificationRequest* notification;
+
+                notification = [self.center getNotificationWithId:id];
+
+                if (!notification)
+                    continue;
 
-            notification = [self.app localNotificationWithId:id];
+                [self.center clearNotification:notification];
+                [self fireEvent:@"clear" notification:notification];
+            }
+        } else {
+            for (NSNumber* id in command.arguments) {
+                UILocalNotification* notification;
+
+                notification = [self.app localNotificationWithId:id];
 
-            if (!notification)
-                continue;
+                if (!notification)
+                    continue;
 
-            [self.app clearLocalNotification:notification];
-            [self fireEvent:@"clear" notification:notification];
+                [self.app clearLocalNotification:notification];
+                [self fireEvent:@"clear" localnotification:notification];
+            }
         }
 
         [self execCallback:command];
@@ -195,7 +262,7 @@
 - (void) clearAll:(CDVInvokedUrlCommand*)command
 {
     [self.commandDelegate runInBackground:^{
-        [self clearAllLocalNotifications];
+        [self clearAllNotifications];
         [self fireEvent:@"clearall"];
         [self execCallback:command];
     }];
@@ -241,20 +308,23 @@
  *      The notification life cycle type
  */
 - (void) isPresent:(CDVInvokedUrlCommand*)command
-              type:(APPLocalNotificationType)type;
+              type:(APPNotificationType)type;
 {
     [self.commandDelegate runInBackground:^{
         NSNumber* id = [command argumentAtIndex:0];
         BOOL exist;
 
-        CDVPluginResult* result;
-
-        if (type == NotifcationTypeAll) {
-            exist = [self.app localNotificationExist:id];
+        if (SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"10.0")) {
+            exist = [self.center notificationExist:id type:type];
         } else {
-            exist = [self.app localNotificationExist:id type:type];
+            if (type == NotifcationTypeAll) {
+                exist = [self.app localNotificationExist:id];
+            } else {
+                exist = [self.app localNotificationExist:id type:type];
+            }
         }
 
+        CDVPluginResult* result;
         result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK
                                      messageAsBool:exist];
 
@@ -296,18 +366,22 @@
  *      The IDs of the notifications
  */
 - (void) getIds:(CDVInvokedUrlCommand*)command
-         byType:(APPLocalNotificationType)type;
+         byType:(APPNotificationType)type;
 {
     [self.commandDelegate runInBackground:^{
-        CDVPluginResult* result;
         NSArray* ids;
 
-        if (type == NotifcationTypeAll) {
-            ids = [self.app localNotificationIds];
+        if (SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"10.0")) {
+            ids = [self.center getNotificationIdsByType:type];
         } else {
-            ids = [self.app localNotificationIdsByType:type];
+            if (type == NotifcationTypeAll) {
+                ids = [self.app localNotificationIds];
+            } else {
+                ids = [self.app localNotificationIdsByType:type];
+            }
         }
 
+        CDVPluginResult* result;
         result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK
                                     messageAsArray:ids];
 
@@ -380,21 +454,26 @@
  *      The ID of the notification
  */
 - (void) getOption:(CDVInvokedUrlCommand*)command
-            byType:(APPLocalNotificationType)type;
+            byType:(APPNotificationType)type;
 {
     [self.commandDelegate runInBackground:^{
         NSArray* ids = command.arguments;
         NSArray* notifications;
-        CDVPluginResult* result;
 
-        if (type == NotifcationTypeAll) {
-            notifications = [self.app localNotificationOptionsById:ids];
-        }
-        else {
-            notifications = [self.app localNotificationOptionsByType:type
-                                                               andId:ids];
+        if (SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"10.0")) {
+            notifications = [self.center getNotificationOptionsByType:type
+                                                                andId:ids];
+        } else {
+            if (type == NotifcationTypeAll) {
+                notifications = [self.app localNotificationOptionsById:ids];
+            }
+            else {
+                notifications = [self.app localNotificationOptionsByType:type
+                                                                   andId:ids];
+            }
         }
 
+        CDVPluginResult* result;
         result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK
                                messageAsDictionary:[notifications firstObject]];
 
@@ -412,27 +491,43 @@
  *      The IDs of the notifications
  */
 - (void) getOptions:(CDVInvokedUrlCommand*)command
-             byType:(APPLocalNotificationType)type;
+             byType:(APPNotificationType)type;
 {
     [self.commandDelegate runInBackground:^{
         NSArray* ids = command.arguments;
         NSArray* notifications;
-        CDVPluginResult* result;
 
-        if (type == NotifcationTypeAll && ids.count == 0) {
-            notifications = [self.app localNotificationOptions];
-        }
-        else if (type == NotifcationTypeAll) {
-            notifications = [self.app localNotificationOptionsById:ids];
-        }
-        else if (ids.count == 0) {
-            notifications = [self.app localNotificationOptionsByType:type];
-        }
-        else {
-            notifications = [self.app localNotificationOptionsByType:type
-                                                               andId:ids];
+        if (SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"10.0")) {
+            if (type == NotifcationTypeAll && ids.count == 0) {
+                notifications = [self.center getNotificationOptions];
+            }
+            else if (type == NotifcationTypeAll) {
+                notifications = [self.center getNotificationOptionsById:ids];
+            }
+            else if (ids.count == 0) {
+                notifications = [self.center getNotificationOptionsByType:type];
+            }
+            else {
+                notifications = [self.center getNotificationOptionsByType:type
+                                                                    andId:ids];
+            }
+        } else {
+            if (type == NotifcationTypeAll && ids.count == 0) {
+                notifications = [self.app localNotificationOptions];
+            }
+            else if (type == NotifcationTypeAll) {
+                notifications = [self.app localNotificationOptionsById:ids];
+            }
+            else if (ids.count == 0) {
+                notifications = [self.app localNotificationOptionsByType:type];
+            }
+            else {
+                notifications = [self.app localNotificationOptionsByType:type
+                                                                   andId:ids];
+            }
         }
 
+        CDVPluginResult* result;
         result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK
                                     messageAsArray:notifications];
 
@@ -447,18 +542,35 @@
  */
 - (void) hasPermission:(CDVInvokedUrlCommand*)command
 {
-    [self.commandDelegate runInBackground:^{
-        CDVPluginResult* result;
-        BOOL hasPermission;
+    if (SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"10.0")) {
+        [self.commandDelegate runInBackground:^{
+            [self.center getNotificationSettingsWithCompletionHandler:^(UNNotificationSettings* settings) {
+                BOOL authorized = settings.authorizationStatus == UNAuthorizationStatusAuthorized;
+                BOOL enabled = settings.notificationCenterSetting == UNNotificationSettingEnabled;
+                BOOL permitted = authorized && enabled;
+                CDVPluginResult* result;
+
+                result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK
+                                             messageAsBool:permitted];
+
+                [self.commandDelegate sendPluginResult:result
+                                            callbackId:command.callbackId];
+            }];
+        }];
+    } else {
+        [self.commandDelegate runInBackground:^{
+            CDVPluginResult* result;
+            BOOL hasPermission;
 
-        hasPermission = [self.app hasPermissionToScheduleLocalNotifications];
+            hasPermission = [self.app hasPermissionToScheduleLocalNotifications];
 
-        result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK
-                                     messageAsBool:hasPermission];
+            result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK
+                                         messageAsBool:hasPermission];
 
-        [self.commandDelegate sendPluginResult:result
-                                    callbackId:command.callbackId];
-    }];
+            [self.commandDelegate sendPluginResult:result
+                                        callbackId:command.callbackId];
+        }];
+    }
 }
 
 /**
@@ -466,16 +578,27 @@
  */
 - (void) registerPermission:(CDVInvokedUrlCommand*)command
 {
-    if ([[UIApplication sharedApplication]
-         respondsToSelector:@selector(registerUserNotificationSettings:)])
-    {
-        _command = command;
-
+    if (SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"10.0")) {
         [self.commandDelegate runInBackground:^{
-            [self.app registerPermissionToScheduleLocalNotifications];
+            UNAuthorizationOptions options =
+            (UNAuthorizationOptionBadge | UNAuthorizationOptionSound | UNAuthorizationOptionAlert);
+
+            [self.center requestAuthorizationWithOptions:options completionHandler:^(BOOL granted, NSError* e) {
+                [self hasPermission:command];
+            }];
         }];
     } else {
-        [self hasPermission:command];
+        if ([[UIApplication sharedApplication]
+             respondsToSelector:@selector(registerUserNotificationSettings:)])
+        {
+            _command = command;
+
+            [self.commandDelegate runInBackground:^{
+                [self.app registerPermissionToScheduleLocalNotifications];
+            }];
+        } else {
+            [self hasPermission:command];
+        }
     }
 }
 
@@ -485,47 +608,219 @@
 /**
  * Schedule the local notification.
  */
-- (void) scheduleLocalNotification:(UILocalNotification*)notification
+- (void) scheduleNotification:(UNMutableNotificationContent*)notification
 {
-    [self cancelForerunnerLocalNotification:notification];
-    [self.app scheduleLocalNotification:notification];
+    [self.center addNotificationRequest:notification.request
+                  withCompletionHandler:^(NSError* e) {
+                      [self fireEvent:@"add" notification:notification.request];
+                  }];
 }
 
 /**
  * Update the local notification.
  */
-- (void) updateLocalNotification:(UILocalNotification*)notification
-                     withOptions:(NSDictionary*)newOptions
+- (void) updateNotification:(UILocalNotification*)notification
+                withOptions:(NSDictionary*)newOptions
 {
     NSMutableDictionary* options = [notification.userInfo mutableCopy];
 
     [options addEntriesFromDictionary:newOptions];
     [options setObject:[NSDate date] forKey:@"updatedAt"];
 
-    notification = [[UILocalNotification alloc]
-                    initWithOptions:options];
-
-    [self scheduleLocalNotification:notification];
+//    notification = [[UILocalNotification alloc]
+//                    initWithOptions:options];
+//
+//    [self scheduleLocalNotification:notification];
 }
 
 /**
  * Cancel all local notifications.
  */
-- (void) cancelAllLocalNotifications
+- (void) cancelAllNotifications
 {
-    [self.app cancelAllLocalNotifications];
+    if (SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"10.0")) {
+        [self.center cancelAllNotifications];
+    } else {
+        [self.app cancelAllLocalNotifications];
+    }
+
     [self.app setApplicationIconBadgeNumber:0];
 }
 
 /**
  * Clear all local notifications.
  */
-- (void) clearAllLocalNotifications
+- (void) clearAllNotifications
 {
-    [self.app clearAllLocalNotifications];
+    if (SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"10.0")) {
+        [self.center clearAllNotifications];
+    } else {
+        [self.app clearAllLocalNotifications];
+    }
+
     [self.app setApplicationIconBadgeNumber:0];
 }
 
+#pragma mark -
+#pragma mark Delegates
+
+/**
+ * Called when a notification is delivered to a foreground app.
+ */
+- (void) userNotificationCenter:(UNUserNotificationCenter *)center
+        willPresentNotification:(UNNotification *)notification
+          withCompletionHandler:(void (^)(UNNotificationPresentationOptions))completionHandler
+{
+    [self fireEvent:@"trigger" notification:notification.request];
+    completionHandler(UNAuthorizationOptionBadge | UNAuthorizationOptionSound | UNAuthorizationOptionAlert);
+}
+
+
+/**
+ * Called to let your app know which action was selected by the user for a given
+ * notification.
+ */
+- (void) userNotificationCenter:(UNUserNotificationCenter *)center
+ didReceiveNotificationResponse:(UNNotificationResponse *)response
+          withCompletionHandler:(void (^)())completionHandler
+{
+    UNNotificationRequest* notification = response.notification.request;
+
+    [self fireEvent:@"click" notification:notification];
+
+    if ([notification.options isRepeating]) {
+        [self.center clearNotification:notification];
+        [self fireEvent:@"clear" notification:notification];
+    } else {
+        [self.center cancelNotification:notification];
+        [self fireEvent:@"cancel" notification:notification];
+    }
+
+    completionHandler();
+}
+
+#pragma mark -
+#pragma mark Life Cycle
+
+/**
+ * Registers obervers after plugin was initialized.
+ */
+- (void) pluginInitialize
+{
+    eventQueue = [[NSMutableArray alloc] init];
+
+    self.center.delegate = self;
+}
+
+#pragma mark -
+#pragma mark Helper
+
+/**
+ * Retrieves the application state
+ *
+ * @return
+ *      Either "background" or "foreground"
+ */
+- (NSString*) applicationState
+{
+    UIApplicationState state = [self.app applicationState];
+
+    bool isActive = state == UIApplicationStateActive;
+
+    return isActive ? @"foreground" : @"background";
+}
+
+/**
+ * Simply invokes the callback without any parameter.
+ */
+- (void) execCallback:(CDVInvokedUrlCommand*)command
+{
+    CDVPluginResult *result = [CDVPluginResult
+                               resultWithStatus:CDVCommandStatus_OK];
+
+    [self.commandDelegate sendPluginResult:result
+                                callbackId:command.callbackId];
+}
+
+/**
+ * Short hand for shared application instance.
+ */
+- (UIApplication*) app
+{
+    return [UIApplication sharedApplication];
+}
+
+/**
+ * Short hand for current notification center.
+ */
+- (UNUserNotificationCenter*) center
+{
+    return [UNUserNotificationCenter currentNotificationCenter];
+}
+
+/**
+ * Fire general event.
+ */
+- (void) fireEvent:(NSString*)event
+{
+    [self fireEvent:event notification:NULL];
+}
+
+/**
+ * Fire event for local notification.
+ */
+- (void) fireEvent:(NSString*)event
+      notification:(UNNotificationRequest*)notification
+{
+    NSString* js;
+    NSString* appState = [self applicationState];
+    NSString* params   = [NSString stringWithFormat:@"\"%@\"", appState];
+
+    if (notification) {
+        NSString* args = [notification encodeToJSON];
+        params = [NSString stringWithFormat:@"%@,'%@'", args, appState];
+    }
+
+    js = [NSString stringWithFormat:
+          @"cordova.plugins.notification.local.core.fireEvent('%@', %@)",
+          event, params];
+
+    if (deviceready) {
+        [self.commandDelegate evalJs:js];
+    } else {
+        [self.eventQueue addObject:js];
+    }
+}
+
+#pragma mark -
+#pragma mark ios 9
+
+/**
+ * Schedule the local notification.
+ */
+- (void) scheduleLocalNotification:(UILocalNotification*)notification
+{
+    [self cancelForerunnerLocalNotification:notification];
+    [self.app scheduleLocalNotification:notification];
+}
+
+/**
+ * Update the local notification.
+ */
+- (void) updateLocalNotification:(UILocalNotification*)notification
+                     withOptions:(NSDictionary*)newOptions
+{
+    NSMutableDictionary* options = [notification.userInfo mutableCopy];
+
+    [options addEntriesFromDictionary:newOptions];
+    [options setObject:[NSDate date] forKey:@"updatedAt"];
+
+    notification = [[UILocalNotification alloc]
+                    initWithOptions:options];
+
+    [self scheduleLocalNotification:notification];
+}
+
 /**
  * Cancel a maybe given forerunner with the same ID.
  */
@@ -558,14 +853,11 @@
             && notification.timeIntervalSinceFireDate > seconds)
         {
             [self.app cancelLocalNotification:notification];
-            [self fireEvent:@"cancel" notification:notification];
+            [self fireEvent:@"cancel" localnotification:notification];
         }
     }
 }
 
-#pragma mark -
-#pragma mark Delegates
-
 /**
  * Calls the cancel or trigger event after a local notification was received.
  * Cancels the local notification if autoCancel was set to true.
@@ -580,16 +872,16 @@
     NSTimeInterval timeInterval = [notification timeIntervalSinceLastTrigger];
     NSString* event = timeInterval < 0.2 && deviceready ? @"trigger" : @"click";
 
-    [self fireEvent:event notification:notification];
+    [self fireEvent:event localnotification:notification];
 
     if (![event isEqualToString:@"click"])
         return;
 
     if ([notification isRepeating]) {
-        [self fireEvent:@"clear" notification:notification];
+        [self fireEvent:@"clear" localnotification:notification];
     } else {
         [self.app cancelLocalNotification:notification];
-        [self fireEvent:@"cancel" notification:notification];
+        [self fireEvent:@"cancel" localnotification:notification];
     }
 }
 
@@ -624,17 +916,6 @@
     }
 }
 
-#pragma mark -
-#pragma mark Life Cycle
-
-/**
- * Registers obervers after plugin was initialized.
- */
-- (void) pluginInitialize
-{
-    eventQueue = [[NSMutableArray alloc] init];
-}
-
 /**
  * Clears all single repeating notifications which are older then 5 days
  * before the app terminates.
@@ -644,98 +925,11 @@
     [self cancelAllNotificationsWhichAreOlderThen:432000];
 }
 
-#pragma mark -
-#pragma mark Helper
-
-/**
- * Retrieves the application state
- *
- * @return
- *      Either "background" or "foreground"
- */
-- (NSString*) applicationState
-{
-    UIApplicationState state = [self.app applicationState];
-
-    bool isActive = state == UIApplicationStateActive;
-
-    return isActive ? @"foreground" : @"background";
-}
-
-/**
- * Simply invokes the callback without any parameter.
- */
-- (void) execCallback:(CDVInvokedUrlCommand*)command
-{
-    CDVPluginResult *result = [CDVPluginResult
-                               resultWithStatus:CDVCommandStatus_OK];
-
-    [self.commandDelegate sendPluginResult:result
-                                callbackId:command.callbackId];
-}
-
-/**
- * Short hand for shared application instance.
- */
-- (UIApplication*) app
-{
-    return [UIApplication sharedApplication];
-}
-
-/**
- * Fire general event.
- */
-- (void) fireEvent:(NSString*)event
-{
-    [self fireEvent:event notification:NULL];
-}
-
 /**
  * Fire event for local notification.
  */
-- (void) fireEvent:(NSString*)event notification:(UILocalNotification*)notification
+- (void) fireEvent:(NSString*)event localnotification:(UILocalNotification*)notification
 {
-    if (IsAtLeastiOSVersion(@"10.0")) {
-        UNMutableNotificationContent *content = [[UNMutableNotificationContent alloc] init];
-        content.title = [NSString localizedUserNotificationStringForKey:notification.alertTitle arguments:nil];
-        content.body = [NSString localizedUserNotificationStringForKey:notification.alertBody
-                                                         arguments:nil];
-        content.sound = [UNNotificationSound defaultSound];
-
-        
-        NSDate *fireDate = notification.fireDate;
-        if(fireDate==nil) {
-            fireDate = [NSDate date];
-        }
-         NSCalendar *gregorianCalendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
-        // Extract all date components into dateComponents
-         NSDateComponents *dateComponents = [gregorianCalendar components:NSYearCalendarUnit | NSMonthCalendarUnit | NSDayCalendarUnit
-         | NSHourCalendarUnit | NSMinuteCalendarUnit | NSSecondCalendarUnit
-                                                           fromDate:fireDate];
-         [dateComponents setTimeZone:[NSTimeZone defaultTimeZone]];
-        
-        /// 4. update application icon badge number
-        //content.badge = @([[UIApplication sharedApplication] applicationIconBadgeNumber] + 1);
-        
-        // Deliver the notification at the fire date.
-        UNCalendarNotificationTrigger *trigger = [UNCalendarNotificationTrigger triggerWithDateMatchingComponents:dateComponents repeats:NO];
-        
-        NSString *identifier = @"DefaultNotificationIdentifier";
-        if(notification.userInfo!=nil && [notification.userInfo objectForKey:@"id"]!=nil) {
-            identifier = [notification.userInfo objectForKey:@"id"];
-        }
-        
-        UNNotificationRequest *request = [UNNotificationRequest requestWithIdentifier:identifier content:content trigger:trigger];
-        
-        /// 3. schedule localNotification
-        UNUserNotificationCenter *center = [UNUserNotificationCenter currentNotificationCenter];
-        [center addNotificationRequest:request withCompletionHandler:^(NSError * _Nullable error) {
-            if (!error) {
-                NSLog(@"add NotificationRequest succeeded!");
-            }
-        }];
-    } 
-
     NSString* js;
     NSString* params = [NSString stringWithFormat:
                         @"\"%@\"", self.applicationState];

+ 11 - 6
src/ios/APPLocalNotificationOptions.h

@@ -20,7 +20,9 @@
  *
  * @APPPLANT_LICENSE_HEADER_END@
  */
- 
+
+#import <UserNotifications/UNNotificationSound.h>
+#import <UserNotifications/UNNotificationRequest.h>
 #import <Foundation/Foundation.h>
 #import <UIKit/UIKit.h>
 
@@ -29,14 +31,17 @@
 - (id) initWithDict:(NSDictionary*)dict;
 
 @property (readonly, getter=id) NSNumber* id;
-@property (readonly, getter=badgeNumber) NSInteger badgeNumber;
-@property (readonly, getter=alertBody) NSString* alertBody;
-@property (readonly, getter=soundName) NSString* soundName;
-@property (readonly, getter=fireDate) NSDate* fireDate;
-@property (readonly, getter=repeatInterval) NSCalendarUnit repeatInterval;
+@property (readonly, getter=identifier) NSString* identifier;
+@property (readonly, getter=title) NSString* title;
+@property (readonly, getter=subtitle) NSString* subtitle;
+@property (readonly, getter=badge) NSNumber* badge;
+@property (readonly, getter=text) NSString* text;
+@property (readonly, getter=sound) UNNotificationSound* sound;
 @property (readonly, getter=userInfo) NSDictionary* userInfo;
 
 // If it's a repeating notification
 - (BOOL) isRepeating;
+// how and when to trigger the notification
+- (UNNotificationTrigger*) trigger;
 
 @end

+ 110 - 78
src/ios/APPLocalNotificationOptions.m

@@ -23,8 +23,7 @@
 
 #import "APPLocalNotificationOptions.h"
 
-// Default sound ressource path
-NSString* const DEFAULT_SOUND = @"res://platform_default";
+@import UserNotifications;
 
 @interface APPLocalNotificationOptions ()
 
@@ -66,6 +65,14 @@ NSString* const DEFAULT_SOUND = @"res://platform_default";
     return [NSNumber numberWithInteger:id];
 }
 
+/**
+ * The notification's ID as a string.
+ */
+- (NSString*) identifier
+{
+    return [NSString stringWithFormat:@"%@", self.id];
+}
+
 /**
  * The notification's title.
  */
@@ -75,63 +82,53 @@ NSString* const DEFAULT_SOUND = @"res://platform_default";
 }
 
 /**
- * The notification's message.
+ * The notification's title.
  */
-- (NSString*) text
+- (NSString*) subtitle
 {
-    return [dict objectForKey:@"text"];
+    NSArray *parts = [self.title componentsSeparatedByString:@"\n"];
+
+    return parts.count < 2 ? @"" : [parts objectAtIndex:1];
 }
 
 /**
- * The notification's badge number.
+ * The notification's message.
  */
-- (NSInteger) badgeNumber
+- (NSString*) text
 {
-    return [[dict objectForKey:@"badge"] intValue];
+    return [dict objectForKey:@"text"];
 }
 
-#pragma mark -
-#pragma mark Complex Attributes
-
 /**
- * The notification's alert body.
+ * The notification's badge number.
  */
-- (NSString*) alertBody
+- (NSNumber*) badge
 {
-    NSString* title = [self title];
-    NSString* msg = [self text];
-
-    NSString* alertBody = msg;
-
-    if (![self stringIsNullOrEmpty:title])
-    {
-        alertBody = [NSString stringWithFormat:@"%@\n%@",
-                     title, msg];
-    }
-
-    return alertBody;
+    return [NSNumber numberWithInt:[[dict objectForKey:@"badge"] intValue]];
 }
 
 /**
  * The notification's sound path.
  */
-- (NSString*) soundName
+- (UNNotificationSound*) sound
 {
     NSString* path = [dict objectForKey:@"sound"];
+    NSString* file;
 
     if ([self stringIsNullOrEmpty:path])
         return NULL;
 
-    if ([path isEqualToString:DEFAULT_SOUND])
-        return UILocalNotificationDefaultSoundName;
+    if ([path isEqualToString:@"res://platform_default"])
+        return [UNNotificationSound defaultSound];
 
-    if ([path hasPrefix:@"file:/"])
-        return [self soundNameForAsset:path];
-
-    if ([path hasPrefix:@"res:"])
-        return [self soundNameForResource:path];
+    if ([path hasPrefix:@"file:/"]) {
+        file = [self soundNameForAsset:path];
+    } else
+    if ([path hasPrefix:@"res:"]) {
+        file = [self soundNameForResource:path];
+    }
 
-    return NULL;
+    return [UNNotificationSound soundNamed:file];
 }
 
 /**
@@ -146,46 +143,26 @@ NSString* const DEFAULT_SOUND = @"res://platform_default";
 }
 
 /**
- * The notification's repeat interval.
+ * If it's a repeating notification.
  */
-- (NSCalendarUnit) repeatInterval
+- (BOOL) isRepeating
 {
     NSString* interval = [dict objectForKey:@"every"];
 
-    if ([self stringIsNullOrEmpty:interval]) {
-        return NSCalendarUnitEra;
-    }
-    else if ([interval isEqualToString:@"second"]) {
-        return NSCalendarUnitSecond;
-    }
-    else if ([interval isEqualToString:@"minute"]) {
-        return NSCalendarUnitMinute;
-    }
-    else if ([interval isEqualToString:@"hour"]) {
-        return NSCalendarUnitHour;
-    }
-    else if ([interval isEqualToString:@"day"]) {
-        return NSCalendarUnitDay;
-    }
-    else if ([interval isEqualToString:@"week"]) {
-        return NSCalendarUnitWeekOfYear;
-    }
-    else if ([interval isEqualToString:@"month"]) {
-        return NSCalendarUnitMonth;
-    }
-    else if ([interval isEqualToString:@"quarter"]) {
-        return NSCalendarUnitQuarter;
-    }
-    else if ([interval isEqualToString:@"year"]) {
-        return NSCalendarUnitYear;
-    }
-
-    return NSCalendarUnitEra;
+    return ![self stringIsNullOrEmpty:interval];
 }
 
 #pragma mark -
 #pragma mark Methods
 
+/**
+ * Specify how and when to trigger the notification.
+ */
+- (UNNotificationTrigger*) trigger
+{
+    return [self isRepeating] ? [self triggerWithDateMatchingComponents] : [self triggerWithTimeInterval];
+}
+
 /**
  * The notification's user info dict.
  */
@@ -202,18 +179,79 @@ NSString* const DEFAULT_SOUND = @"res://platform_default";
     return dict;
 }
 
+#pragma mark -
+#pragma mark Private
+
 /**
- * If it's a repeating notification.
+ * Returns a trigger based on a custom time interval in seconds.
  */
-- (BOOL) isRepeating
+- (UNTimeIntervalNotificationTrigger*) triggerWithTimeInterval
 {
-    NSCalendarUnit interval = self.repeatInterval;
+    return [UNTimeIntervalNotificationTrigger
+            triggerWithTimeInterval:[self timeInterval] repeats:NO];
+}
+
+/**
+ * Returns a trigger based on a calendar time.
+ */
+- (UNCalendarNotificationTrigger*) triggerWithDateMatchingComponents
+{
+    NSCalendar* cal = [[NSCalendar alloc]
+                       initWithCalendarIdentifier:NSCalendarIdentifierGregorian];
+
+    NSDateComponents *date = [cal components:[self repeatInterval]
+                                    fromDate:[self fireDate]];
 
-    return !(interval == NSCalendarUnitEra || interval == 0);
+    [date setTimeZone:[NSTimeZone defaultTimeZone]];
+
+    return [UNCalendarNotificationTrigger
+            triggerWithDateMatchingComponents:date repeats:YES];
 }
 
-#pragma mark -
-#pragma mark Helpers
+/**
+ * Timeinterval between future fire date and now.
+ */
+- (double) timeInterval
+{
+    return MAX(0.01f, [self.fireDate timeIntervalSinceDate:[NSDate date]]);
+}
+
+/**
+ * The notification's repeat interval.
+ */
+- (NSCalendarUnit) repeatInterval
+{
+    NSString* interval = [dict objectForKey:@"every"];
+    NSCalendarUnit unitFlags = NSCalendarUnitYear|NSCalendarUnitMonth|NSCalendarUnitDay|NSCalendarUnitHour|NSCalendarUnitMinute|NSCalendarUnitSecond;
+
+
+    if ([self stringIsNullOrEmpty:interval]) {
+        return unitFlags;
+    }
+    else if ([interval isEqualToString:@"second"]) {
+        return NSCalendarUnitYear|NSCalendarUnitMonth|NSCalendarUnitDay;
+    }
+    else if ([interval isEqualToString:@"minute"]) {
+        return NSCalendarUnitYear|NSCalendarUnitMonth|NSCalendarUnitDay|NSCalendarUnitSecond;
+    }
+    else if ([interval isEqualToString:@"hour"]) {
+        return NSCalendarUnitYear|NSCalendarUnitMonth|NSCalendarUnitDay|NSCalendarUnitMinute;
+    }
+    else if ([interval isEqualToString:@"day"]) {
+        return NSCalendarUnitHour|NSCalendarUnitMinute;
+    }
+    else if ([interval isEqualToString:@"week"]) {
+        return NSCalendarUnitWeekday|NSCalendarUnitHour|NSCalendarUnitMinute;
+    }
+    else if ([interval isEqualToString:@"month"]) {
+        return NSCalendarUnitDay|NSCalendarUnitHour|NSCalendarUnitMinute;
+    }
+    else if ([interval isEqualToString:@"year"]) {
+        return NSCalendarUnitMonth|NSCalendarUnitDay|NSCalendarUnitHour|NSCalendarUnitMinute;
+    }
+
+    return unitFlags;
+}
 
 /**
  * Convert relative path to valid sound name attribute.
@@ -237,13 +275,7 @@ NSString* const DEFAULT_SOUND = @"res://platform_default";
  */
 - (BOOL) stringIsNullOrEmpty:(NSString*)str
 {
-    if (str == (NSString*)[NSNull null])
-        return YES;
-
-    if ([str isEqualToString:@""])
-        return YES;
-
-    return NO;
+    return (!str.length);
 }
 
 @end

+ 39 - 0
src/ios/UNMutableNotificationContent+APPLocalNotification.h

@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2013-2015 by appPlant UG. All rights reserved.
+ *
+ * @APPPLANT_LICENSE_HEADER_START@
+ *
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apache License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. Please obtain a copy of the License at
+ * http://opensource.org/licenses/Apache-2.0/ and read it before using this
+ * file.
+ *
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * @APPPLANT_LICENSE_HEADER_END@
+ */
+
+#import "APPLocalNotificationOptions.h"
+
+@import UserNotifications;
+
+@interface UNMutableNotificationContent (APPLocalNotification)
+
+// Initialize a new local notification
+- (id) initWithOptions:(NSDictionary*)dict;
+// The options provided by the plug-in
+- (APPLocalNotificationOptions*) options;
+// Fully configured request to add the notification to the notification center
+- (UNNotificationRequest*) request;
+// Encode the user info dict to JSON
+- (NSString*) encodeToJSON;
+
+@end

+ 142 - 0
src/ios/UNMutableNotificationContent+APPLocalNotification.m

@@ -0,0 +1,142 @@
+/*
+ * Copyright (c) 2013-2015 by appPlant UG. All rights reserved.
+ *
+ * @APPPLANT_LICENSE_HEADER_START@
+ *
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apache License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. Please obtain a copy of the License at
+ * http://opensource.org/licenses/Apache-2.0/ and read it before using this
+ * file.
+ *
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * @APPPLANT_LICENSE_HEADER_END@
+ */
+
+#import "UNMutableNotificationContent+APPLocalNotification.h"
+#import "APPLocalNotificationOptions.h"
+#import <objc/runtime.h>
+
+@import UserNotifications;
+
+static char optionsKey;
+
+@implementation UNMutableNotificationContent (APPLocalNotification)
+
+#pragma mark -
+#pragma mark Init
+
+/**
+ * Initialize a local notification with the given options when calling on JS side:
+ * notification.local.add(options)
+ */
+- (id) initWithOptions:(NSDictionary*)dict
+{
+    self = [self init];
+
+    [self setUserInfo:dict];
+    [self __init];
+
+    return self;
+}
+
+/**
+ * Applies the given options when calling on JS side:
+ * notification.local.add(options)
+
+ */
+- (void) __init
+{
+    APPLocalNotificationOptions* options = self.options;
+
+    self.title    = options.title;
+    self.subtitle = options.subtitle;
+    self.body     = options.text;
+    self.sound    = options.sound;
+    self.badge    = options.badge;
+}
+
+#pragma mark -
+#pragma mark Methods
+
+/**
+ * The options provided by the plug-in.
+ */
+- (APPLocalNotificationOptions*) options
+{
+    APPLocalNotificationOptions* options = [self getOptions];
+
+    if (!options) {
+        options = [[APPLocalNotificationOptions alloc]
+                   initWithDict:[self userInfo]];
+
+        [self setOptions:options];
+    }
+
+    return options;
+}
+
+/**
+ * Get associated option object
+ */
+- (APPLocalNotificationOptions*) getOptions
+{
+    return objc_getAssociatedObject(self, &optionsKey);
+}
+
+/**
+ * Set associated option object
+ */
+- (void) setOptions:(APPLocalNotificationOptions*)options
+{
+    objc_setAssociatedObject(self, &optionsKey,
+                             options, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
+}
+
+/**
+ * The notifcations request ready to add to the notification center including
+ * all informations about trigger behavior.
+ */
+- (UNNotificationRequest*) request
+{
+    APPLocalNotificationOptions* opts = [self getOptions];
+
+    return [UNNotificationRequest requestWithIdentifier:opts.identifier
+                                                content:self
+                                                trigger:opts.trigger];
+}
+
+/**
+ * Encode the user info dict to JSON.
+ */
+- (NSString*) encodeToJSON
+{
+    NSString* json;
+    NSData* data;
+    NSMutableDictionary* obj = [self.userInfo mutableCopy];
+
+    [obj removeObjectForKey:@"updatedAt"];
+
+    if (obj == NULL || obj.count == 0)
+        return json;
+
+    data = [NSJSONSerialization dataWithJSONObject:obj
+                                           options:NSJSONWritingPrettyPrinted
+                                             error:NULL];
+
+    json = [[NSString alloc] initWithData:data
+                                 encoding:NSUTF8StringEncoding];
+
+    return [json stringByReplacingOccurrencesOfString:@"\n"
+                                           withString:@""];
+}
+
+@end

+ 33 - 0
src/ios/UNNotificationRequest+APPLocalNotification.h

@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2013-2015 by appPlant UG. All rights reserved.
+ *
+ * @APPPLANT_LICENSE_HEADER_START@
+ *
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apache License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. Please obtain a copy of the License at
+ * http://opensource.org/licenses/Apache-2.0/ and read it before using this
+ * file.
+ *
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * @APPPLANT_LICENSE_HEADER_END@
+ */
+
+@import UserNotifications;
+
+@interface UNNotificationRequest (APPLocalNotification)
+
+// The options provided by the plug-in
+- (APPLocalNotificationOptions*) options;
+// Encode the user info dict to JSON
+- (NSString*) encodeToJSON;
+
+@end

+ 94 - 0
src/ios/UNNotificationRequest+APPLocalNotification.m

@@ -0,0 +1,94 @@
+/*
+ * Copyright (c) 2013-2015 by appPlant UG. All rights reserved.
+ *
+ * @APPPLANT_LICENSE_HEADER_START@
+ *
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apache License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. Please obtain a copy of the License at
+ * http://opensource.org/licenses/Apache-2.0/ and read it before using this
+ * file.
+ *
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * @APPPLANT_LICENSE_HEADER_END@
+ */
+
+#import "UNMutableNotificationContent+APPLocalNotification.h"
+#import "APPLocalNotificationOptions.h"
+#import "UNNotificationRequest+APPLocalNotification.h"
+#import <objc/runtime.h>
+
+@import UserNotifications;
+
+static char optionsKey;
+
+@implementation UNNotificationRequest (APPLocalNotification)
+
+/**
+ * Get associated option object
+ */
+- (APPLocalNotificationOptions*) getOptions
+{
+    return objc_getAssociatedObject(self, &optionsKey);
+}
+
+/**
+ * Set associated option object
+ */
+- (void) setOptions:(APPLocalNotificationOptions*)options
+{
+    objc_setAssociatedObject(self, &optionsKey,
+                             options, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
+}
+
+/**
+ * The options provided by the plug-in.
+ */
+- (APPLocalNotificationOptions*) options
+{
+    APPLocalNotificationOptions* options = [self getOptions];
+
+    if (!options) {
+        options = [[APPLocalNotificationOptions alloc]
+                   initWithDict:[self.content userInfo]];
+
+        [self setOptions:options];
+    }
+
+    return options;
+}
+
+/**
+ * Encode the user info dict to JSON.
+ */
+- (NSString*) encodeToJSON
+{
+    NSString* json;
+    NSData* data;
+    NSMutableDictionary* obj = [self.content.userInfo mutableCopy];
+
+    [obj removeObjectForKey:@"updatedAt"];
+
+    if (obj == NULL || obj.count == 0)
+        return json;
+
+    data = [NSJSONSerialization dataWithJSONObject:obj
+                                           options:NSJSONWritingPrettyPrinted
+                                             error:NULL];
+
+    json = [[NSString alloc] initWithData:data
+                                 encoding:NSUTF8StringEncoding];
+
+    return [json stringByReplacingOccurrencesOfString:@"\n"
+                                           withString:@""];
+}
+
+@end

+ 71 - 0
src/ios/UNUserNotificationCenter+APPLocalNotification.h

@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2013-2015 by appPlant UG. All rights reserved.
+ *
+ * @APPPLANT_LICENSE_HEADER_START@
+ *
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apache License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. Please obtain a copy of the License at
+ * http://opensource.org/licenses/Apache-2.0/ and read it before using this
+ * file.
+ *
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * @APPPLANT_LICENSE_HEADER_END@
+ */
+
+#import "UNMutableNotificationContent+APPLocalNotification.h"
+
+@interface UNUserNotificationCenter (APPLocalNotification)
+
+typedef NS_ENUM(NSUInteger, APPNotificationType) {
+    NotifcationTypeAll = 0,
+    NotifcationTypeScheduled = 1,
+    NotifcationTypeTriggered = 2
+};
+
+#define APPNotificationType_DEFINED
+
+@property (readonly, getter=getNotifications) NSArray* localNotifications;
+@property (readonly, getter=getNotificationIds) NSArray* localNotificationIds;
+
+// List of all notification IDs from given type
+- (NSArray*) getNotificationIdsByType:(APPNotificationType)type;
+
+// Find out if notification with ID exists
+- (BOOL) notificationExist:(NSNumber*)id;
+// Find out if notification with ID and type exists
+- (BOOL) notificationExist:(NSNumber*)id type:(APPNotificationType)type;
+
+// Find notification by ID
+- (UNNotificationRequest*) getNotificationWithId:(NSNumber*)id;
+// Find notification by ID and type
+- (UNNotificationRequest*) getNotificationWithId:(NSNumber*)id andType:(APPNotificationType)type;
+
+// Property list from all local notifications
+- (NSArray*) getNotificationOptions;
+// Property list from given local notifications
+- (NSArray*) getNotificationOptionsById:(NSArray*)ids;
+// Property list from all local notifications with type constraint
+- (NSArray*) getNotificationOptionsByType:(APPNotificationType)type;
+// Property list from given local notifications with type constraint
+- (NSArray*) getNotificationOptionsByType:(APPNotificationType)type andId:(NSArray*)ids;
+
+// Clear specified notfication
+- (void) clearNotification:(UNNotificationRequest*)notification;
+// Clear all notfications
+- (void) clearAllNotifications;
+
+// Cancel specified notfication
+- (void) cancelNotification:(UNNotificationRequest*)notification;
+// Cancel all notfications
+- (void) cancelAllNotifications;
+
+@end

+ 305 - 0
src/ios/UNUserNotificationCenter+APPLocalNotification.m

@@ -0,0 +1,305 @@
+/*
+ * Copyright (c) 2013-2015 by appPlant UG. All rights reserved.
+ *
+ * @APPPLANT_LICENSE_HEADER_START@
+ *
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apache License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. Please obtain a copy of the License at
+ * http://opensource.org/licenses/Apache-2.0/ and read it before using this
+ * file.
+ *
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * @APPPLANT_LICENSE_HEADER_END@
+ */
+
+#import "UNUserNotificationCenter+APPLocalNotification.h"
+#import "UNNotificationRequest+APPLocalNotification.h"
+
+@import UserNotifications;
+
+@implementation UNUserNotificationCenter (APPLocalNotification)
+
+#pragma mark -
+#pragma mark LocalNotifications
+
+/**
+ * List of all delivered or still pending notifications.
+ */
+- (NSArray*) getNotifications
+{
+    NSMutableArray* notifications = [[NSMutableArray alloc] init];
+
+    [notifications addObjectsFromArray:[self getPendingNotifications]];
+    [notifications addObjectsFromArray:[self getDeliveredNotifications]];
+
+    return notifications;
+}
+
+/**
+ * List of all triggered notifications.
+ */
+- (NSArray*) getDeliveredNotifications
+{
+    NSMutableArray* notifications = [[NSMutableArray alloc] init];
+    dispatch_semaphore_t sema = dispatch_semaphore_create(0);
+
+    [self getDeliveredNotificationsWithCompletionHandler:^(NSArray<UNNotification *> *delivered) {
+        for (UNNotification* notification in delivered) {
+            [notifications addObject:notification.request];
+        }
+        dispatch_semaphore_signal(sema);
+    }];
+
+    dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER);
+
+    return notifications;
+}
+
+/**
+ * List of all pending notifications.
+ */
+- (NSArray*) getPendingNotifications
+{
+    NSMutableArray* notifications = [[NSMutableArray alloc] init];
+    dispatch_semaphore_t sema = dispatch_semaphore_create(0);
+
+    [self getPendingNotificationRequestsWithCompletionHandler:^(NSArray<UNNotificationRequest *> *requests) {
+        [notifications addObjectsFromArray:requests];
+        dispatch_semaphore_signal(sema);
+    }];
+
+    dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER);
+
+    return notifications;
+}
+
+/**
+ * List of all notifications from given type.
+ *
+ * @param type
+ *      Notification life cycle type
+ */
+- (NSArray*) getNotificationsByType:(APPNotificationType)type
+{
+    switch (type) {
+        case NotifcationTypeScheduled:
+            return [self getPendingNotifications];
+
+        case NotifcationTypeTriggered:
+            return [self getDeliveredNotifications];
+
+        default:
+            return [self getNotifications];
+    }
+}
+
+/**
+ * List of all local notifications IDs.
+ */
+- (NSArray*) getNotificationIds
+{
+    NSArray* notifications = [self getNotifications];
+    NSMutableArray* ids    = [[NSMutableArray alloc] init];
+
+    for (UNNotificationRequest* notification in notifications)
+    {
+        [ids addObject:notification.options.id];
+    }
+
+    return ids;
+}
+
+/**
+ * List of all notifications IDs from given type.
+ *
+ * @param type
+ *      Notification life cycle type
+ */
+- (NSArray*) getNotificationIdsByType:(APPNotificationType)type
+{
+    NSArray* notifications = [self getNotificationsByType:type];
+    NSMutableArray* ids    = [[NSMutableArray alloc] init];
+
+    for (UNNotificationRequest* notification in notifications)
+    {
+        [ids addObject:notification.options.id];
+    }
+
+    return ids;
+}
+
+/*
+ * If the notification with the specified ID does exists.
+ *
+ * @param id
+ *      Notification ID
+ */
+- (BOOL) notificationExist:(NSNumber*)id
+{
+    return [self getNotificationWithId:id] != NULL;
+}
+
+/* If the notification with specified ID and type exists.
+ *
+ * @param id
+ *      Notification ID
+ * @param type
+ *      Notification life cycle type
+ */
+- (BOOL) notificationExist:(NSNumber*)id type:(APPNotificationType)type
+{
+    return [self getNotificationWithId:id andType:type] != NULL;
+}
+
+/**
+ * Find notification by ID.
+ *
+ * @param id
+ *      Notification ID
+ */
+- (UNNotificationRequest*) getNotificationWithId:(NSNumber*)id
+{
+    return [self getNotificationWithId:id andType:NotifcationTypeAll];
+}
+
+/*
+ * Find notification by ID and type.
+ *
+ * @param id
+ *      Notification ID
+ * @param type
+ *      Notification life cycle type
+ */
+- (UNNotificationRequest*) getNotificationWithId:(NSNumber*)id andType:(APPNotificationType)type
+{
+    NSArray* notifications = [self getNotificationsByType:type];
+
+    for (UNNotificationRequest* notification in notifications)
+    {
+        NSString* fid = [NSString stringWithFormat:@"%@", notification.options.id];
+
+        if ([fid isEqualToString:[id stringValue]]) {
+            return notification;
+        }
+    }
+
+    return NULL;
+}
+
+/**
+ * List of properties from all notifications.
+ */
+- (NSArray*) getNotificationOptions
+{
+    return [self getNotificationOptionsByType:NotifcationTypeAll];
+}
+
+/**
+ * List of properties from all notifications of given type.
+ *
+ * @param type
+ *      Notification life cycle type
+ */
+- (NSArray*) getNotificationOptionsByType:(APPNotificationType)type
+{
+    NSArray* notifications  = [self getNotificationsByType:type];
+    NSMutableArray* options = [[NSMutableArray alloc] init];
+
+    for (UNNotificationRequest* notification in notifications)
+    {
+        [options addObject:notification.options.userInfo];
+    }
+
+    return options;
+}
+
+/**
+ * List of properties from given local notifications.
+ *
+ * @param ids
+ *      Notification IDs
+ */
+- (NSArray*) getNotificationOptionsById:(NSArray*)ids
+{
+    return [self getNotificationOptionsByType:NotifcationTypeAll andId:ids];
+}
+
+/**
+ * List of properties from given local notifications.
+ *
+ * @param type
+ *      Notification life cycle type
+ * @param ids
+ *      Notification IDs
+ */
+- (NSArray*) getNotificationOptionsByType:(APPNotificationType)type andId:(NSArray*)ids
+{
+    NSArray* notifications  = [self getNotificationsByType:type];
+    NSMutableArray* options = [[NSMutableArray alloc] init];
+
+    for (UNNotificationRequest* notification in notifications)
+    {
+        if ([ids containsObject:notification.options.id]) {
+            [options addObject:notification.options.userInfo];
+        }
+    }
+
+    return options;
+}
+
+/*
+ * Clear all notfications.
+ */
+- (void) clearAllNotifications
+{
+    [self removeAllDeliveredNotifications];
+}
+
+/*
+ * Clear Specified notfication.
+ *
+ * @param notification
+ *      The notification object
+ */
+- (void) clearNotification:(UNNotificationRequest*)notification
+{
+    NSArray* ids = [[NSArray alloc]
+                    initWithObjects:notification.identifier, nil];
+
+    [self removeDeliveredNotificationsWithIdentifiers:ids];
+}
+
+/*
+ * Cancel all notfications.
+ */
+- (void) cancelAllNotifications
+{
+    [self removeAllPendingNotificationRequests];
+    [self removeAllDeliveredNotifications];
+}
+
+/*
+ * Cancel specified notfication.
+ *
+ * @param notification
+ *      The notification object
+ */
+- (void) cancelNotification:(UNNotificationRequest*)notification
+{
+    NSArray* ids = [[NSArray alloc]
+                    initWithObjects:notification.identifier, nil];
+
+    [self removeDeliveredNotificationsWithIdentifiers:ids];
+    [self removePendingNotificationRequestsWithIdentifiers:ids];
+}
+
+@end

+ 78 - 0
src/ios9/APPLocalNotification.ios9.h

@@ -0,0 +1,78 @@
+/*
+ * Copyright (c) 2013-2015 by appPlant UG. All rights reserved.
+ *
+ * @APPPLANT_LICENSE_HEADER_START@
+ *
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apache License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. Please obtain a copy of the License at
+ * http://opensource.org/licenses/Apache-2.0/ and read it before using this
+ * file.
+ *
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * @APPPLANT_LICENSE_HEADER_END@
+ */
+
+#import <Foundation/Foundation.h>
+#import <Cordova/CDVPlugin.h>
+
+@interface APPLocalNotification9 : CDVPlugin
+
+// Execute all queued events
+- (void) deviceready:(CDVInvokedUrlCommand*)command;
+
+// Inform if the app has the permission to show notifications
+- (void) hasPermission:(CDVInvokedUrlCommand*)command;
+// Register permission to show notifications
+- (void) registerPermission:(CDVInvokedUrlCommand*)command;
+
+// Schedule set of notifications
+- (void) schedule:(CDVInvokedUrlCommand*)command;
+// Update set of notifications
+- (void) update:(CDVInvokedUrlCommand*)command;
+// Cancel set of notifications
+- (void) cancel:(CDVInvokedUrlCommand*)command;
+// Cancel all notifications
+- (void) cancelAll:(CDVInvokedUrlCommand*)command;
+// Clear set of notifications
+- (void) clear:(CDVInvokedUrlCommand*)command;
+// Clear all notifications
+- (void) clearAll:(CDVInvokedUrlCommand*)command;
+
+// If a notification with an ID is present
+- (void) isPresent:(CDVInvokedUrlCommand*)command;
+// If a notification with an ID is scheduled
+- (void) isScheduled:(CDVInvokedUrlCommand*)command;
+// If a notification with an ID is triggered
+- (void) isTriggered:(CDVInvokedUrlCommand*)command;
+
+// List all ids from all local notifications
+- (void) getAllIds:(CDVInvokedUrlCommand*)command;
+// List all ids from all pending notifications
+- (void) getScheduledIds:(CDVInvokedUrlCommand*)command;
+// List all ids from all triggered notifications
+- (void) getTriggeredIds:(CDVInvokedUrlCommand*)command;
+
+// Propertys for given local notification
+- (void) getSingle:(CDVInvokedUrlCommand*)command;
+// Propertya for given scheduled notification
+- (void) getSingleScheduled:(CDVInvokedUrlCommand*)command;
+// Propertys for given triggered notification
+- (void) getSingleTriggered:(CDVInvokedUrlCommand*)command;
+
+// Property list for given local notifications
+- (void) getAll:(CDVInvokedUrlCommand*)command;
+// Property list for given scheduled notifications
+- (void) getScheduled:(CDVInvokedUrlCommand*)command;
+// Property list for given triggered notifications
+- (void) getTriggered:(CDVInvokedUrlCommand*)command;
+
+@end

+ 717 - 0
src/ios9/APPLocalNotification.ios9.m

@@ -0,0 +1,717 @@
+/*
+ * Copyright (c) 2013-2015 by appPlant UG. All rights reserved.
+ *
+ * @APPPLANT_LICENSE_HEADER_START@
+ *
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apache License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. Please obtain a copy of the License at
+ * http://opensource.org/licenses/Apache-2.0/ and read it before using this
+ * file.
+ *
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * @APPPLANT_LICENSE_HEADER_END@
+ */
+
+#import "APPLocalNotification.ios9.h"
+#import "APPLocalNotificationOptions.ios9.h"
+#import "UIApplication+APPLocalNotification.ios9.h"
+#import "UILocalNotification+APPLocalNotification.ios9.h"
+
+@interface APPLocalNotification9 ()
+
+// Retrieves the application state
+@property (readonly, getter=applicationState) NSString* applicationState;
+// All events will be queued until deviceready has been fired
+@property (readwrite, assign) BOOL deviceready;
+// Event queue
+@property (readonly, nonatomic, retain) NSMutableArray* eventQueue;
+// Needed when calling `registerPermission`
+@property (nonatomic, retain) CDVInvokedUrlCommand* command;
+
+@end
+
+@implementation APPLocalNotification9
+
+@synthesize deviceready, eventQueue;
+
+#pragma mark -
+#pragma mark Interface
+
+/**
+ * Execute all queued events.
+ */
+- (void) deviceready:(CDVInvokedUrlCommand*)command
+{
+    deviceready = YES;
+
+    for (NSString* js in eventQueue) {
+        [self.commandDelegate evalJs:js];
+    }
+
+    [eventQueue removeAllObjects];
+}
+
+/**
+ * Schedule a set of notifications.
+ *
+ * @param properties
+ *      A dict of properties for each notification
+ */
+- (void) schedule:(CDVInvokedUrlCommand*)command
+{
+    NSArray* notifications = command.arguments;
+
+    [self.commandDelegate runInBackground:^{
+        for (NSDictionary* options in notifications) {
+            UILocalNotification* notification;
+
+            notification = [[UILocalNotification alloc]
+                            initWithOptions:options];
+
+            [self scheduleLocalNotification:[notification copy]];
+            [self fireEvent:@"schedule" notification:notification];
+
+            if (notifications.count > 1) {
+                [NSThread sleepForTimeInterval:0.01];
+            }
+        }
+
+        [self execCallback:command];
+    }];
+}
+
+/**
+ * Update a set of notifications.
+ *
+ * @param properties
+ *      A dict of properties for each notification
+ */
+- (void) update:(CDVInvokedUrlCommand*)command
+{
+    NSArray* notifications = command.arguments;
+
+    [self.commandDelegate runInBackground:^{
+        for (NSDictionary* options in notifications) {
+            NSNumber* id = [options objectForKey:@"id"];
+            UILocalNotification* notification;
+
+            notification = [self.app localNotificationWithId:id];
+
+            if (!notification)
+                continue;
+
+            [self updateLocalNotification:[notification copy]
+                              withOptions:options];
+
+            [self fireEvent:@"update" notification:notification];
+
+            if (notifications.count > 1) {
+                [NSThread sleepForTimeInterval:0.01];
+            }
+        }
+
+        [self execCallback:command];
+    }];
+}
+
+/**
+ * Cancel a set of notifications.
+ *
+ * @param ids
+ *      The IDs of the notifications
+ */
+- (void) cancel:(CDVInvokedUrlCommand*)command
+{
+    [self.commandDelegate runInBackground:^{
+        for (NSNumber* id in command.arguments) {
+            UILocalNotification* notification;
+
+            notification = [self.app localNotificationWithId:id];
+
+            if (!notification)
+                continue;
+
+            [self.app cancelLocalNotification:notification];
+            [self fireEvent:@"cancel" notification:notification];
+        }
+
+        [self execCallback:command];
+    }];
+}
+
+/**
+ * Cancel all local notifications.
+ */
+- (void) cancelAll:(CDVInvokedUrlCommand*)command
+{
+    [self.commandDelegate runInBackground:^{
+        [self cancelAllLocalNotifications];
+        [self fireEvent:@"cancelall"];
+        [self execCallback:command];
+    }];
+}
+
+/**
+ * Clear a set of notifications.
+ *
+ * @param ids
+ *      The IDs of the notifications
+ */
+- (void) clear:(CDVInvokedUrlCommand*)command
+{
+    [self.commandDelegate runInBackground:^{
+        for (NSNumber* id in command.arguments) {
+            UILocalNotification* notification;
+
+            notification = [self.app localNotificationWithId:id];
+
+            if (!notification)
+                continue;
+
+            [self.app clearLocalNotification:notification];
+            [self fireEvent:@"clear" notification:notification];
+        }
+
+        [self execCallback:command];
+    }];
+}
+
+/**
+ * Clear all local notifications.
+ */
+- (void) clearAll:(CDVInvokedUrlCommand*)command
+{
+    [self.commandDelegate runInBackground:^{
+        [self clearAllLocalNotifications];
+        [self fireEvent:@"clearall"];
+        [self execCallback:command];
+    }];
+}
+
+/**
+ * If a notification by ID is present.
+ *
+ * @param id
+ *      The ID of the notification
+ */
+- (void) isPresent:(CDVInvokedUrlCommand *)command
+{
+    [self isPresent:command type:NotifcationTypeAll];
+}
+
+/**
+ * If a notification by ID is scheduled.
+ *
+ * @param id
+ *      The ID of the notification
+ */
+- (void) isScheduled:(CDVInvokedUrlCommand*)command
+{
+    [self isPresent:command type:NotifcationTypeScheduled];
+}
+
+/**
+ * Check if a notification with an ID is triggered.
+ *
+ * @param id
+ *      The ID of the notification
+ */
+- (void) isTriggered:(CDVInvokedUrlCommand*)command
+{
+    [self isPresent:command type:NotifcationTypeTriggered];
+}
+
+/**
+ * Check if a notification with an ID exists.
+ *
+ * @param type
+ *      The notification life cycle type
+ */
+- (void) isPresent:(CDVInvokedUrlCommand*)command
+              type:(APPNotificationType)type;
+{
+    [self.commandDelegate runInBackground:^{
+        NSNumber* id = [command argumentAtIndex:0];
+        BOOL exist;
+
+        CDVPluginResult* result;
+
+        if (type == NotifcationTypeAll) {
+            exist = [self.app localNotificationExist:id];
+        } else {
+            exist = [self.app localNotificationExist:id type:type];
+        }
+
+        result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK
+                                     messageAsBool:exist];
+
+        [self.commandDelegate sendPluginResult:result
+                                    callbackId:command.callbackId];
+    }];
+}
+
+/**
+ * List all ids from all local notifications.
+ */
+- (void) getAllIds:(CDVInvokedUrlCommand*)command
+{
+    [self getIds:command byType:NotifcationTypeAll];
+}
+
+/**
+ * List all ids from all pending notifications.
+ */
+- (void) getScheduledIds:(CDVInvokedUrlCommand*)command
+{
+    [self getIds:command byType:NotifcationTypeScheduled];
+}
+
+/**
+ * List all ids from all triggered notifications.
+ */
+- (void) getTriggeredIds:(CDVInvokedUrlCommand*)command
+{
+    [self getIds:command byType:NotifcationTypeTriggered];
+}
+
+/**
+ * List of ids for given local notifications.
+ *
+ * @param type
+ *      Notification life cycle type
+ * @param ids
+ *      The IDs of the notifications
+ */
+- (void) getIds:(CDVInvokedUrlCommand*)command
+         byType:(APPNotificationType)type;
+{
+    [self.commandDelegate runInBackground:^{
+        CDVPluginResult* result;
+        NSArray* ids;
+
+        if (type == NotifcationTypeAll) {
+            ids = [self.app localNotificationIds];
+        } else {
+            ids = [self.app localNotificationIdsByType:type];
+        }
+
+        result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK
+                                    messageAsArray:ids];
+
+        [self.commandDelegate sendPluginResult:result
+                                    callbackId:command.callbackId];
+    }];
+}
+
+/**
+ * Propertys for given local notification.
+ */
+- (void) getSingle:(CDVInvokedUrlCommand*)command
+{
+    [self getOption:command byType:NotifcationTypeAll];
+}
+
+/**
+ * Propertya for given scheduled notification.
+ */
+- (void) getSingleScheduled:(CDVInvokedUrlCommand*)command
+{
+    [self getOption:command byType:NotifcationTypeScheduled];
+}
+
+// Propertys for given triggered notification
+- (void) getSingleTriggered:(CDVInvokedUrlCommand*)command
+{
+    [self getOption:command byType:NotifcationTypeTriggered];
+}
+
+/**
+ * Property list for given local notifications.
+ *
+ * @param ids
+ *      The IDs of the notifications
+ */
+- (void) getAll:(CDVInvokedUrlCommand*)command
+{
+    [self getOptions:command byType:NotifcationTypeAll];
+}
+
+/**
+ * Property list for given scheduled notifications.
+ *
+ * @param ids
+ *      The IDs of the notifications
+ */
+- (void) getScheduled:(CDVInvokedUrlCommand*)command
+{
+    [self getOptions:command byType:NotifcationTypeScheduled];
+}
+
+/**
+ * Property list for given triggered notifications.
+ *
+ * @param ids
+ *      The IDs of the notifications
+ */
+- (void) getTriggered:(CDVInvokedUrlCommand *)command
+{
+    [self getOptions:command byType:NotifcationTypeTriggered];
+}
+
+/**
+ * Propertys for given triggered notification.
+ *
+ * @param type
+ *      Notification life cycle type
+ * @param ids
+ *      The ID of the notification
+ */
+- (void) getOption:(CDVInvokedUrlCommand*)command
+            byType:(APPNotificationType)type;
+{
+    [self.commandDelegate runInBackground:^{
+        NSArray* ids = command.arguments;
+        NSArray* notifications;
+        CDVPluginResult* result;
+
+        if (type == NotifcationTypeAll) {
+            notifications = [self.app localNotificationOptionsById:ids];
+        }
+        else {
+            notifications = [self.app localNotificationOptionsByType:type
+                                                               andId:ids];
+        }
+
+        result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK
+                               messageAsDictionary:[notifications firstObject]];
+
+        [self.commandDelegate sendPluginResult:result
+                                    callbackId:command.callbackId];
+    }];
+}
+
+/**
+ * Property list for given triggered notifications.
+ *
+ * @param type
+ *      Notification life cycle type
+ * @param ids
+ *      The IDs of the notifications
+ */
+- (void) getOptions:(CDVInvokedUrlCommand*)command
+             byType:(APPNotificationType)type;
+{
+    [self.commandDelegate runInBackground:^{
+        NSArray* ids = command.arguments;
+        NSArray* notifications;
+        CDVPluginResult* result;
+
+        if (type == NotifcationTypeAll && ids.count == 0) {
+            notifications = [self.app localNotificationOptions];
+        }
+        else if (type == NotifcationTypeAll) {
+            notifications = [self.app localNotificationOptionsById:ids];
+        }
+        else if (ids.count == 0) {
+            notifications = [self.app localNotificationOptionsByType:type];
+        }
+        else {
+            notifications = [self.app localNotificationOptionsByType:type
+                                                               andId:ids];
+        }
+
+        result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK
+                                    messageAsArray:notifications];
+
+        [self.commandDelegate sendPluginResult:result
+                                    callbackId:command.callbackId];
+    }];
+}
+
+/**
+ * Inform if the app has the permission to show
+ * badges and local notifications.
+ */
+- (void) hasPermission:(CDVInvokedUrlCommand*)command
+{
+    [self.commandDelegate runInBackground:^{
+        CDVPluginResult* result;
+        BOOL hasPermission;
+
+        hasPermission = [self.app hasPermissionToScheduleLocalNotifications];
+
+        result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK
+                                     messageAsBool:hasPermission];
+
+        [self.commandDelegate sendPluginResult:result
+                                    callbackId:command.callbackId];
+    }];
+}
+
+/**
+ * Ask for permission to show badges.
+ */
+- (void) registerPermission:(CDVInvokedUrlCommand*)command
+{
+    if ([[UIApplication sharedApplication]
+         respondsToSelector:@selector(registerUserNotificationSettings:)])
+    {
+        _command = command;
+
+        [self.commandDelegate runInBackground:^{
+            [self.app registerPermissionToScheduleLocalNotifications];
+        }];
+    } else {
+        [self hasPermission:command];
+    }
+}
+
+#pragma mark -
+#pragma mark Core Logic
+
+/**
+ * Schedule the local notification.
+ */
+- (void) scheduleLocalNotification:(UILocalNotification*)notification
+{
+    [self cancelForerunnerLocalNotification:notification];
+    [self.app scheduleLocalNotification:notification];
+}
+
+/**
+ * Update the local notification.
+ */
+- (void) updateLocalNotification:(UILocalNotification*)notification
+                     withOptions:(NSDictionary*)newOptions
+{
+    NSMutableDictionary* options = [notification.userInfo mutableCopy];
+
+    [options addEntriesFromDictionary:newOptions];
+    [options setObject:[NSDate date] forKey:@"updatedAt"];
+
+    notification = [[UILocalNotification alloc]
+                    initWithOptions:options];
+
+    [self scheduleLocalNotification:notification];
+}
+
+/**
+ * Cancel all local notifications.
+ */
+- (void) cancelAllLocalNotifications
+{
+    [self.app cancelAllLocalNotifications];
+    [self.app setApplicationIconBadgeNumber:0];
+}
+
+/**
+ * Clear all local notifications.
+ */
+- (void) clearAllLocalNotifications
+{
+    [self.app clearAllLocalNotifications];
+    [self.app setApplicationIconBadgeNumber:0];
+}
+
+/**
+ * Cancel a maybe given forerunner with the same ID.
+ */
+- (void) cancelForerunnerLocalNotification:(UILocalNotification*)notification
+{
+    NSNumber* id = notification.options.id;
+    UILocalNotification* forerunner;
+
+    forerunner = [self.app localNotificationWithId:id];
+
+    if (!forerunner)
+        return;
+
+    [self.app cancelLocalNotification:forerunner];
+}
+
+/**
+ * Cancels all non-repeating local notification older then
+ * a specific amount of seconds
+ */
+- (void) cancelAllNotificationsWhichAreOlderThen:(float)seconds
+{
+    NSArray* notifications;
+
+    notifications = [self.app localNotifications];
+
+    for (UILocalNotification* notification in notifications)
+    {
+        if (![notification isRepeating]
+            && notification.timeIntervalSinceFireDate > seconds)
+        {
+            [self.app cancelLocalNotification:notification];
+            [self fireEvent:@"cancel" notification:notification];
+        }
+    }
+}
+
+#pragma mark -
+#pragma mark Delegates
+
+/**
+ * Calls the cancel or trigger event after a local notification was received.
+ * Cancels the local notification if autoCancel was set to true.
+ */
+- (void) didReceiveLocalNotification:(NSNotification*)localNotification
+{
+    UILocalNotification* notification = [localNotification object];
+
+    if ([notification userInfo] == NULL || [notification wasUpdated])
+        return;
+
+    NSTimeInterval timeInterval = [notification timeIntervalSinceLastTrigger];
+    NSString* event = timeInterval < 0.2 && deviceready ? @"trigger" : @"click";
+
+    [self fireEvent:event notification:notification];
+
+    if (![event isEqualToString:@"click"])
+        return;
+
+    if ([notification isRepeating]) {
+        [self fireEvent:@"clear" notification:notification];
+    } else {
+        [self.app cancelLocalNotification:notification];
+        [self fireEvent:@"cancel" notification:notification];
+    }
+}
+
+/**
+ * Called when app has started
+ * (by clicking on a local notification).
+ */
+- (void) didFinishLaunchingWithOptions:(NSNotification*)notification
+{
+    NSDictionary* launchOptions = [notification userInfo];
+
+    UILocalNotification* localNotification;
+
+    localNotification = [launchOptions objectForKey:
+                         UIApplicationLaunchOptionsLocalNotificationKey];
+
+    if (localNotification) {
+        [self didReceiveLocalNotification:
+         [NSNotification notificationWithName:CDVLocalNotification
+                                       object:localNotification]];
+    }
+}
+
+/**
+ * Called on otification settings registration is completed.
+ */
+- (void) didRegisterUserNotificationSettings:(UIUserNotificationSettings*)settings
+{
+    if (_command) {
+        [self hasPermission:_command];
+        _command = NULL;
+    }
+}
+
+#pragma mark -
+#pragma mark Life Cycle
+
+/**
+ * Registers obervers after plugin was initialized.
+ */
+- (void) pluginInitialize
+{
+    eventQueue = [[NSMutableArray alloc] init];
+}
+
+/**
+ * Clears all single repeating notifications which are older then 5 days
+ * before the app terminates.
+ */
+- (void) onAppTerminate
+{
+    [self cancelAllNotificationsWhichAreOlderThen:432000];
+}
+
+#pragma mark -
+#pragma mark Helper
+
+/**
+ * Retrieves the application state
+ *
+ * @return
+ *      Either "background" or "foreground"
+ */
+- (NSString*) applicationState
+{
+    UIApplicationState state = [self.app applicationState];
+
+    bool isActive = state == UIApplicationStateActive;
+
+    return isActive ? @"foreground" : @"background";
+}
+
+/**
+ * Simply invokes the callback without any parameter.
+ */
+- (void) execCallback:(CDVInvokedUrlCommand*)command
+{
+    CDVPluginResult *result = [CDVPluginResult
+                               resultWithStatus:CDVCommandStatus_OK];
+
+    [self.commandDelegate sendPluginResult:result
+                                callbackId:command.callbackId];
+}
+
+/**
+ * Short hand for shared application instance.
+ */
+- (UIApplication*) app
+{
+    return [UIApplication sharedApplication];
+}
+
+/**
+ * Fire general event.
+ */
+- (void) fireEvent:(NSString*)event
+{
+    [self fireEvent:event notification:NULL];
+}
+
+/**
+ * Fire event for local notification.
+ */
+- (void) fireEvent:(NSString*)event notification:(UILocalNotification*)notification
+{
+    NSString* js;
+    NSString* params = [NSString stringWithFormat:
+                        @"\"%@\"", self.applicationState];
+
+    if (notification) {
+        NSString* args = [notification encodeToJSON];
+
+        params = [NSString stringWithFormat:
+                  @"%@,'%@'",
+                  args, self.applicationState];
+    }
+
+    js = [NSString stringWithFormat:
+          @"cordova.plugins.notification.local.core.fireEvent('%@', %@)",
+          event, params];
+
+    if (deviceready) {
+        [self.commandDelegate evalJs:js];
+    } else {
+        [self.eventQueue addObject:js];
+    }
+}
+
+@end

+ 42 - 0
src/ios9/APPLocalNotificationOptions.ios9.h

@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2013-2015 by appPlant UG. All rights reserved.
+ *
+ * @APPPLANT_LICENSE_HEADER_START@
+ *
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apache License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. Please obtain a copy of the License at
+ * http://opensource.org/licenses/Apache-2.0/ and read it before using this
+ * file.
+ *
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * @APPPLANT_LICENSE_HEADER_END@
+ */
+    
+#import <Foundation/Foundation.h>
+#import <UIKit/UIKit.h>
+
+@interface APPLocalNotificationOptions9 : NSObject
+
+- (id) initWithDict:(NSDictionary*)dict;
+
+@property (readonly, getter=id) NSNumber* id;
+@property (readonly, getter=badgeNumber) NSInteger badgeNumber;
+@property (readonly, getter=alertBody) NSString* alertBody;
+@property (readonly, getter=soundName) NSString* soundName;
+@property (readonly, getter=fireDate) NSDate* fireDate;
+@property (readonly, getter=repeatInterval) NSCalendarUnit repeatInterval;
+@property (readonly, getter=userInfo) NSDictionary* userInfo;
+
+// If it's a repeating notification
+- (BOOL) isRepeating;
+
+@end

+ 246 - 0
src/ios9/APPLocalNotificationOptions.ios9.m

@@ -0,0 +1,246 @@
+/*
+ * Copyright (c) 2013-2015 by appPlant UG. All rights reserved.
+ *
+ * @APPPLANT_LICENSE_HEADER_START@
+ *
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apache License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. Please obtain a copy of the License at
+ * http://opensource.org/licenses/Apache-2.0/ and read it before using this
+ * file.
+ *
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * @APPPLANT_LICENSE_HEADER_END@
+ */
+
+#import "APPLocalNotificationOptions.ios9.h"
+
+@interface APPLocalNotificationOptions9 ()
+
+// The dictionary which contains all notification properties
+@property(nonatomic, retain) NSDictionary* dict;
+
+@end
+
+@implementation APPLocalNotificationOptions9
+
+@synthesize dict;
+
+#pragma mark -
+#pragma mark Initialization
+
+/**
+ * Initialize the object with the given options when calling on JS side:
+ * notification.local.add(options)
+ */
+- (id) initWithDict:(NSDictionary*)dictionary
+{
+    self = [self init];
+
+    self.dict = dictionary;
+
+    return self;
+}
+
+#pragma mark -
+#pragma mark Attributes
+
+/**
+ * The notification's ID.
+ */
+- (NSNumber*) id
+{
+    NSInteger id = [[dict objectForKey:@"id"] integerValue];
+
+    return [NSNumber numberWithInteger:id];
+}
+
+/**
+ * The notification's title.
+ */
+- (NSString*) title
+{
+    return [dict objectForKey:@"title"];
+}
+
+/**
+ * The notification's message.
+ */
+- (NSString*) text
+{
+    return [dict objectForKey:@"text"];
+}
+
+/**
+ * The notification's badge number.
+ */
+- (NSInteger) badgeNumber
+{
+    return [[dict objectForKey:@"badge"] intValue];
+}
+
+#pragma mark -
+#pragma mark Complex Attributes
+
+/**
+ * The notification's alert body.
+ */
+- (NSString*) alertBody
+{
+    NSString* title = [self title];
+    NSString* msg = [self text];
+
+    NSString* alertBody = msg;
+
+    if (![self stringIsNullOrEmpty:title])
+    {
+        alertBody = [NSString stringWithFormat:@"%@\n%@",
+                     title, msg];
+    }
+
+    return alertBody;
+}
+
+/**
+ * The notification's sound path.
+ */
+- (NSString*) soundName
+{
+    NSString* path = [dict objectForKey:@"sound"];
+
+    if ([self stringIsNullOrEmpty:path])
+        return NULL;
+
+    if ([path isEqualToString:@"res://platform_default"])
+        return UILocalNotificationDefaultSoundName;
+
+    if ([path hasPrefix:@"file:/"])
+        return [self soundNameForAsset:path];
+
+    if ([path hasPrefix:@"res:"])
+        return [self soundNameForResource:path];
+
+    return NULL;
+}
+
+/**
+ * The notification's fire date.
+ */
+- (NSDate*) fireDate
+{
+    double timestamp = [[dict objectForKey:@"at"]
+                        doubleValue];
+
+    return [NSDate dateWithTimeIntervalSince1970:timestamp];
+}
+
+/**
+ * The notification's repeat interval.
+ */
+- (NSCalendarUnit) repeatInterval
+{
+    NSString* interval = [dict objectForKey:@"every"];
+
+    if ([self stringIsNullOrEmpty:interval]) {
+        return NSCalendarUnitEra;
+    }
+    else if ([interval isEqualToString:@"second"]) {
+        return NSCalendarUnitSecond;
+    }
+    else if ([interval isEqualToString:@"minute"]) {
+        return NSCalendarUnitMinute;
+    }
+    else if ([interval isEqualToString:@"hour"]) {
+        return NSCalendarUnitHour;
+    }
+    else if ([interval isEqualToString:@"day"]) {
+        return NSCalendarUnitDay;
+    }
+    else if ([interval isEqualToString:@"week"]) {
+        return NSCalendarUnitWeekOfYear;
+    }
+    else if ([interval isEqualToString:@"month"]) {
+        return NSCalendarUnitMonth;
+    }
+    else if ([interval isEqualToString:@"quarter"]) {
+        return NSCalendarUnitQuarter;
+    }
+    else if ([interval isEqualToString:@"year"]) {
+        return NSCalendarUnitYear;
+    }
+
+    return NSCalendarUnitEra;
+}
+
+#pragma mark -
+#pragma mark Methods
+
+/**
+ * The notification's user info dict.
+ */
+- (NSDictionary*) userInfo
+{
+    if ([dict objectForKey:@"updatedAt"]) {
+        NSMutableDictionary* data = [dict mutableCopy];
+
+        [data removeObjectForKey:@"updatedAt"];
+
+        return data;
+    }
+
+    return dict;
+}
+
+/**
+ * If it's a repeating notification.
+ */
+- (BOOL) isRepeating
+{
+    NSCalendarUnit interval = self.repeatInterval;
+
+    return !(interval == NSCalendarUnitEra || interval == 0);
+}
+
+#pragma mark -
+#pragma mark Helpers
+
+/**
+ * Convert relative path to valid sound name attribute.
+ */
+- (NSString*) soundNameForAsset:(NSString*)path
+{
+    return [path stringByReplacingOccurrencesOfString:@"file:/"
+                                           withString:@"www"];
+}
+
+/**
+ * Convert resource path to valid sound name attribute.
+ */
+- (NSString*) soundNameForResource:(NSString*)path
+{
+    return [path pathComponents].lastObject;
+}
+
+/**
+ * If the string is empty.
+ */
+- (BOOL) stringIsNullOrEmpty:(NSString*)str
+{
+    if (str == (NSString*)[NSNull null])
+        return YES;
+
+    if ([str isEqualToString:@""])
+        return YES;
+
+    return NO;
+}
+
+@end

+ 6 - 6
src/ios/UIApplication+APPLocalNotification.h → src/ios9/UIApplication+APPLocalNotification.ios9.h

@@ -21,7 +21,7 @@
  * @APPPLANT_LICENSE_HEADER_END@
  */
 
-#import "UILocalNotification+APPLocalNotification.h"
+#import "UILocalNotification+APPLocalNotification.ios9.h"
 
 @interface UIApplication (APPLocalNotification)
 
@@ -34,26 +34,26 @@
 - (void) registerPermissionToScheduleLocalNotifications;
 
 // List of all local notification IDs from given type
-- (NSArray*) localNotificationIdsByType:(APPLocalNotificationType)type;
+- (NSArray*) localNotificationIdsByType:(APPNotificationType)type;
 
 // If local notification with ID exists
 - (BOOL) localNotificationExist:(NSNumber*)id;
 // If local notification with ID and type exists
-- (BOOL) localNotificationExist:(NSNumber*)id type:(APPLocalNotificationType)type;
+- (BOOL) localNotificationExist:(NSNumber*)id type:(APPNotificationType)type;
 
 // Local notification by ID
 - (UILocalNotification*) localNotificationWithId:(NSNumber*)id;
 // Local notification by ID and type
-- (UILocalNotification*) localNotificationWithId:(NSNumber*)id andType:(APPLocalNotificationType)type;
+- (UILocalNotification*) localNotificationWithId:(NSNumber*)id andType:(APPNotificationType)type;
 
 // Property list from all local notifications
 - (NSArray*) localNotificationOptions;
 // Property list from given local notifications
 - (NSArray*) localNotificationOptionsById:(NSArray*)ids;
 // Property list from all local notifications with type constraint
-- (NSArray*) localNotificationOptionsByType:(APPLocalNotificationType)type;
+- (NSArray*) localNotificationOptionsByType:(APPNotificationType)type;
 // Property list from given local notifications with type constraint
-- (NSArray*) localNotificationOptionsByType:(APPLocalNotificationType)type andId:(NSArray*)ids;
+- (NSArray*) localNotificationOptionsByType:(APPNotificationType)type andId:(NSArray*)ids;
 
 // Clear single local notfications
 - (void) clearLocalNotification:(UILocalNotification*)notification;

+ 7 - 7
src/ios/UIApplication+APPLocalNotification.m → src/ios9/UIApplication+APPLocalNotification.ios9.m

@@ -21,8 +21,8 @@
  * @APPPLANT_LICENSE_HEADER_END@
  */
 
-#import "UIApplication+APPLocalNotification.h"
-#import "UILocalNotification+APPLocalNotification.h"
+#import "UIApplication+APPLocalNotification.ios9.h"
+#import "UILocalNotification+APPLocalNotification.ios9.h"
 
 @implementation UIApplication (APPLocalNotification)
 
@@ -138,7 +138,7 @@
  * @param type
  *      Notification life cycle type
  */
-- (NSArray*) localNotificationIdsByType:(APPLocalNotificationType)type
+- (NSArray*) localNotificationIdsByType:(APPNotificationType)type
 {
     NSArray* notifications = self.localNotifications;
     NSMutableArray* ids = [[NSMutableArray alloc] init];
@@ -171,7 +171,7 @@
  * @param type
  *      Notification life cycle type
  */
-- (BOOL) localNotificationExist:(NSNumber*)id type:(APPLocalNotificationType)type
+- (BOOL) localNotificationExist:(NSNumber*)id type:(APPNotificationType)type
 {
     return [self localNotificationWithId:id andType:type] != NULL;
 }
@@ -206,7 +206,7 @@
  * @param type
  *      Notification life cycle type
  */
-- (UILocalNotification*) localNotificationWithId:(NSNumber*)id andType:(APPLocalNotificationType)type
+- (UILocalNotification*) localNotificationWithId:(NSNumber*)id andType:(APPNotificationType)type
 {
     UILocalNotification* notification = [self localNotificationWithId:id];
 
@@ -238,7 +238,7 @@
  * @param type
  *      Notification life cycle type
  */
-- (NSArray*) localNotificationOptionsByType:(APPLocalNotificationType)type
+- (NSArray*) localNotificationOptionsByType:(APPNotificationType)type
 {
     NSArray* notifications = self.localNotifications;
     NSMutableArray* options = [[NSMutableArray alloc] init];
@@ -284,7 +284,7 @@
  * @param ids
  *      Notification IDs
  */
-- (NSArray*) localNotificationOptionsByType:(APPLocalNotificationType)type andId:(NSArray*)ids
+- (NSArray*) localNotificationOptionsByType:(APPNotificationType)type andId:(NSArray*)ids
 {
     UILocalNotification* notification;
     NSMutableArray* options = [[NSMutableArray alloc] init];

+ 6 - 4
src/ios/UILocalNotification+APPLocalNotification.h → src/ios9/UILocalNotification+APPLocalNotification.ios9.h

@@ -21,20 +21,22 @@
  * @APPPLANT_LICENSE_HEADER_END@
  */
 
-#import "APPLocalNotificationOptions.h"
+#import "APPLocalNotificationOptions.ios9.h"
 
-typedef NS_ENUM(NSUInteger, APPLocalNotificationType) {
+#ifndef APPNotificationType_DEFINED
+typedef NS_ENUM(NSUInteger, APPNotificationType) {
     NotifcationTypeAll = 0,
     NotifcationTypeScheduled = 1,
     NotifcationTypeTriggered = 2
 };
+#endif
 
 @interface UILocalNotification (APPLocalNotification)
 
 // Initialize a new local notification
 - (id) initWithOptions:(NSDictionary*)dict;
 // The options provided by the plug-in
-- (APPLocalNotificationOptions*) options;
+- (APPLocalNotificationOptions9*) options;
 // Timeinterval since last trigger date
 - (double) timeIntervalSinceLastTrigger;
 // Timeinterval since fire date
@@ -50,7 +52,7 @@ typedef NS_ENUM(NSUInteger, APPLocalNotificationType) {
 // If it's a repeating notification
 - (BOOL) isRepeating;
 // Notifciation type
-- (APPLocalNotificationType) type;
+- (APPNotificationType) type;
 // Encode the user info dict to JSON
 - (NSString*) encodeToJSON;
 

+ 9 - 9
src/ios/UILocalNotification+APPLocalNotification.m → src/ios9/UILocalNotification+APPLocalNotification.ios9.m

@@ -21,8 +21,8 @@
  * @APPPLANT_LICENSE_HEADER_END@
  */
 
-#import "UILocalNotification+APPLocalNotification.h"
-#import "APPLocalNotificationOptions.h"
+#import "UILocalNotification+APPLocalNotification.ios9.h"
+#import "APPLocalNotificationOptions.ios9.h"
 #import <objc/runtime.h>
 
 static char optionsKey;
@@ -56,7 +56,7 @@ NSInteger const APPLocalNotificationTypeTriggered = 2;
  */
 - (void) __init
 {
-    APPLocalNotificationOptions* options = self.options;
+    APPLocalNotificationOptions9* options = self.options;
 
     self.fireDate = options.fireDate;
     self.timeZone = [NSTimeZone defaultTimeZone];
@@ -76,12 +76,12 @@ NSInteger const APPLocalNotificationTypeTriggered = 2;
 /**
  * The options provided by the plug-in.
  */
-- (APPLocalNotificationOptions*) options
+- (APPLocalNotificationOptions9*) options
 {
-    APPLocalNotificationOptions* options = [self getOptions];
+    APPLocalNotificationOptions9* options = [self getOptions];
 
     if (!options) {
-        options = [[APPLocalNotificationOptions alloc]
+        options = [[APPLocalNotificationOptions9 alloc]
                    initWithDict:[self userInfo]];
 
         [self setOptions:options];
@@ -93,7 +93,7 @@ NSInteger const APPLocalNotificationTypeTriggered = 2;
 /**
  * Get associated option object
  */
-- (APPLocalNotificationOptions*) getOptions
+- (APPLocalNotificationOptions9*) getOptions
 {
     return objc_getAssociatedObject(self, &optionsKey);
 }
@@ -101,7 +101,7 @@ NSInteger const APPLocalNotificationTypeTriggered = 2;
 /**
  * Set associated option object
  */
-- (void) setOptions:(APPLocalNotificationOptions*)options
+- (void) setOptions:(APPLocalNotificationOptions9*)options
 {
     objc_setAssociatedObject(self, &optionsKey,
                              options, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
@@ -239,7 +239,7 @@ NSInteger const APPLocalNotificationTypeTriggered = 2;
 /**
  * Process state type of the local notification.
  */
-- (APPLocalNotificationType) type
+- (APPNotificationType) type
 {
     return [self isTriggered] ? NotifcationTypeTriggered : NotifcationTypeScheduled;
 }