NAV Navbar
Swift Objective-C
  • Spotz CNC Customer SDK (Click & Collect)
  • Prerequisites
  • Getting Started
  • Basic Setup
  • Delegates and Data Sources
  • Customer Authentication
  • Orders
  • Notifications
  • License
  • Spotz CNC Customer SDK (Click & Collect)

    The Localz Click and Collect SDK allows retailers to integrate into Localz platform to capture geofence triggers, deliver alerts, notify store staff and help deliver a sleek Click&Collect experience.

    This SDK documentation is based on:

    iOS version 1.11.4

    Prerequisites

    Minimum OS: iOS 9

    Swift compatibility: Swift 5.1

    Services used:

    Dependencies:

    Getting Started

    1. Install SpotzCNCCustomerSDK

    Create a podfile from the terminal with pod init

    # Spec repositories
    source 'https://github.com/localz/Spotz-iOS-Specs.git'
    source 'https://github.com/CocoaPods/Specs.git'
    
    # Pod
    pod 'SpotzCNCCustomerSDK'
    

    Add references to the Localz and CocoaPods spec repositories to the podfile, and add the SpotzCNCCustomerSDK pod to the podfile

    Install SpotzCNCCustomerSDK and dependencies from the terminal with pod update. This will create an Xcode workspace which you will use instead of the Xcode project going forward.

    2. Import SpotzCNCCustomerSDK

    If writing in Swift, import the SpotzCNCCustomerSDK module, and import the SpotzCNCCustomerSDK umbrella header in a bridging header.

    If writing in Objective-C, make sure there is at least one Swift file (even if it's blank) in the project so the compiler knows to compile Swift files.

    Import the Swift compatibility header and SpotzCNCCustomerSDK umbrella header.

    import SpotzCNCCustomerSDK
    
    #import <SpotzCNCCustomerSDK/SpotzCNCCustomerSDK-Swift.h>
    #import <SpotzCNCCustomerSDK/SpotzCNCCustomerSDK.h>
    

    3. Project Configuration

    To enable the SDK capabilities navigate to the project target's Signing & Capabilities tab and add the Background Modes capability.

    Enable the following background modes:

    iOS background capabilities

    Next navigate to the Info tab (or the project's Info.plist file) and add the following keys with relevant descriptions to be displayed to the user upon prompt for each permission.

    Location permission is requested to receive store geofence and iBeacon events, and in some cases significant location updates to monitor only the nearest stores.

    Bluetooth permission is request to manage state when iBeacons are in use.

    4. Using the Customer SDK

    The standard flow of initialisation is:

    1. App calls initWithAppId:spotzAppKey:cncAppKey:delegate:dataSource:options:
    2. CNC SDK Delegate calls either spotzCNCSDKInitSuccessful or spotzCNCSDKInitFailed:
    3. App calls promptLocationServices
    4. App calls startNotificationServices
    5. iOS calls application:didRegisterForRemoteNotificationsWithDeviceToken: (if the user gave permission)
    6. App calls startSpotzCNC

    Continue to read about implementing this and more.

    Basic Setup

    Initialisation

    SpotzCNCCustomerSDK.initWithAppId(<#projectId#>, spotzAppKey: <#projectKey#>, cncAppKey: <#cncKey#>, delegate: self, dataSource: self, options: nil)
    
    [SpotzCNCCustomerSDK initWithAppId:<#projectId#> spotzAppKey:<#projectKey#> cncAppKey:<#cncKey#> delegate:self dataSource:self options:nil];
    

    To initialise the SDK the keys required are:

    options dictionary key/value pairs (available SpotzCNCCustomerSDK 1.11.2 & SpotzSDK 3.2.9 onwards):

    Contact Localz if you do not already have the required keys.

    Delegate Conformance and Starting Services

    extension <#MyClass#>: SpotzCNCCustomerSDKDelegate {
    
        func spotzCNCSDKInitSuccessful() {
    
            SpotzCNCCustomerSDK.shared().promptLocationServices()
            SpotzCNCCustomerSDK.shared().startNotificationServices()
            SpotzCNCCustomerSDK.shared().startSpotzCNC()
        }
    
        func spotzCNCSDKInitFailed(error: NSError!) {
    
            print("SpotzCNCCustomerSDK initalisation failed with error \(error)")
        }
    }
    
    @interface <#MyClass#> () <SpotzCNCCustomerSDKManagerDelegate>
    @end
    
    @implementation <#MyClass#>
    
    - (void)spotzCNCSDKInitSuccessful {
    
        [[SpotzCNCCustomerSDK shared] promptLocationServices];
        [[SpotzCNCCustomerSDK shared] startNotificationServices];
        [[SpotzCNCCustomerSDK shared] startSpotzCNC];
    }
    
    - (void)spotzCNCSDKInitFailed:(NSError *)error {
    
        NSLog(@"SpotzCNCCustomerSDK initalisation failed with error %@", error);
    }
    
    @end
    

    Next, conform to the SpotzCNCCustomerSDKDelegate by implementing the following methods:

    These delegate methods may be used to start the necessary services as well as the SDK, but it is recommended to start each service individually by taking the user through an onboarding process that explains how their data will be used.

    Push Notifications

    To link the app push notifications to the SDK, implement the following delegate methods in the AppDelegate

    func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
    
        SpotzCNCCustomerSDK.shared()?.applicationDidRegisterForRemoteNotifications(withDeviceToken: deviceToken)
    }
    
    func application(_ application: UIApplication, didFailToRegisterForRemoteNotificationsWithError error: Error) {
    
        SpotzCNCCustomerSDK.shared()?.applicationDidFailToRegisterForRemoteNotificationsWithError(error)
    }
    
    func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any], fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) {
    
        SpotzCNCCustomerSDK.shared()?.applicationDidReceiveRemoteNotification(userInfo, applicationState: application.applicationState, fetchCompletionHandler: completionHandler)
    }
    
    // Before iOS13
    {
        "aps" : {
            "alert" : "Push notification",
            "action" : "order_ready",
            "orderNumber" : "44500045"
        }
    }
    // After iOS13
    {
        "aps" : {
            "alert" : "Push notification"
        }
        "action" : "order_ready",
        "orderNumber" : "44500045"
    }
    
    - (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken {
    
        [[SpotzCNCCustomerSDK shared] applicationDidRegisterForRemoteNotificationsWithDeviceToken:deviceToken];
    }
    
    - (void)application:(UIApplication *)application didFailToRegisterForRemoteNotificationsWithError:(NSError *)error {
    
        [[SpotzCNCCustomerSDK shared] applicationDidFailToRegisterForRemoteNotificationsWithError:error];
    }
    
    - (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler {
    
        [[SpotzCNCCustomerSDK shared] applicationDidReceiveRemoteNotification:userInfo applicationState:application.applicationState fetchCompletionHandler:completionHandler];
    }
    
    // Before iOS13
    {
        "aps" : {
            "alert" : "Push notification",
            "action" : "order_ready",
            "orderNumber" : "44500045"
        }
    }
    // After iOS13
    {
        "aps" : {
            "alert" : "Push notification"
        }
        "action" : "order_ready",
        "orderNumber" : "44500045"
    }
    

    Delegates and Data Sources

    There are a number of other delegate and data source methods available to implement if necessary.

    Please see the Push Notification section for more detail on the notification delegates.

    Delegate - SpotzCNCCustomerSDKManagerDelegate

    // Required
    - (void)spotzCNCSDKInitSuccessful
    - (void)spotzCNCSDKInitFailed:(NSError *)error
    // Optional
    - (BOOL)spotzCNCSDKShouldRecordActivityForSpot:(SpotzData *)spot activity:(SpotzCNCActivityType)activity order:(SpotzCNCOrder *)order
    - (void)spotzCNCSDKConfirmedCustomerRegistration
    - (void)spotzCNCSDKUpdateOrders:(NSArray *)orders
    - (void)spotzCNCSDKCompletedOrderPickup:(SpotzCNCOrder *)order
    - (void)spotzCNCSDKBluetoothStateChanged:(BOOL)enabled
    - (void)spotzCNCSDKLocationServicesStateChanged:(BOOL)enabled
    - (void)spotzCNCSDKNotificationDidSelectActionAtIndex:(int)index order:(SpotzCNCOrder *)order
    
    // Required
    func spotzCNCSDKInitSuccessful()
    func spotzCNCSDKInitFailed(_ error: Error!)
    // Optional
    func spotzCNCSDKShouldRecordActivity(forSpot spot: SpotzData!, activity: SpotzCNCActivityType, order: SpotzCNCOrder!) -> Bool
    func spotzCNCSDKConfirmedCustomerRegistration()
    func spotzCNCSDKUpdateOrders(_ orders: [Any]!)
    func spotzCNCSDKCompletedOrderPickup(_ order: SpotzCNCOrder!)
    func spotzCNCSDKBluetoothStateChanged(_ enabled: Bool)
    func spotzCNCSDKLocationServicesStateChanged(_ enabled: Bool)
    func spotzCNCSDKNotificationDidSelectAction(at index: Int32, order: SpotzCNCOrder!)
    

    Required

    Optional

    Data Source - SpotzCNCCustomerSDKManagerDataSource

    // Optional
    - (NSDictionary *)spotzCNCSDKRecordActivityAttributesForSpot:(SpotzData *)spot
    - (BOOL)spotzCNCSDKNotificationMessagePresentCheckinOptionsForOrder:(SpotzCNCOrder *)order
    - (int)spotzCNCSDKNotificationNumberOfActions
    - (NSString *)spotzCNCSDKNotificationActionTitleForIndex:(int)index
    - (SpotzCNCNotification * _Nullable)spotzCNCSDKNotificationOnSiteEntry:(SpotzSiteDetails * _Nonnull)site order:(SpotzCNCOrder * _Nullable)order
    - (SpotzCNCNotification * _Nullable)spotzCNCSDKNotificationWhenCheckingInOrder:(SpotzCNCOrder * _Nullable)order error:(NSError * _Nullable)error
    // Legacy
    - (NSString *)spotzCNCSDKNotificationMessageWhenEnteringStore:(SpotzCNCLocationStore *)store order:(SpotzCNCOrder *)order
    - (NSString *)spotzCNCSDKNotificationMessageWhenOrderCheckedInBackground:(SpotzCNCOrder *)order
    - (NSString *)spotzCNCSDKNotificationMessageWhenOrderCheckedInBackground:(SpotzCNCOrder *)order error:(NSError *)error
    
    // Optional
    func spotzCNCSDKRecordActivityAttributes(forSpot spot: SpotzData!) -> [AnyHashable : Any]!
    func spotzCNCSDKNotificationMessagePresentCheckinOptions(for order: SpotzCNCOrder!) -> Bool
    func spotzCNCSDKNotificationNumberOfActions() -> Int32
    func spotzCNCSDKNotificationActionTitle(for index: Int32) -> String!
    func spotzCNCSDKNotification(onSiteEntry site: SpotzSiteDetails, order: SpotzCNCOrder?) -> SpotzCNCNotification?
    func spotzCNCSDKNotificationWhenChecking(in order: SpotzCNCOrder?, error: Error?) -> SpotzCNCNotification?
    // Legacy
    func spotzCNCSDKNotificationMessage(whenEntering store: SpotzCNCLocationStore!, order: SpotzCNCOrder!) -> String!
    func spotzCNCSDKNotificationMessageWhenOrderChecked(inBackground order: SpotzCNCOrder!) -> String!
    func spotzCNCSDKNotificationMessageWhenOrderChecked(inBackground order: SpotzCNCOrder!, error: Error!) -> String!
    

    Optional

    Legacy

    Consider using spotzCNCSDKNotificationOnSiteEntry:order: and spotzCNCSDKNotificationWhenCheckingInOrder:error: instead, as the below methods may be deprecated in the future.

    Customer Authentication

    1. Register a Customer

    Using Email

    // Using email
    SpotzCNCCustomerSDK.shared().registerCustomerWithEmail("customeremail@localz.com", otherParameters: nil) { (error:NSError!) -> Void in
    
        if (error == nil) {
            print("Registered! Click email verification link to start using CNC")
        } else {
            print("Failed to register email with error \(error)")
        }
    }
    
    // Using email
    [[SpotzCNCCustomerSDK shared] registerCustomerWithEmail:@"customeremail@localz.com" otherParameters:nil completion:^(NSError *error) {
    
        if (!error) {
            NSLog(@"Registered! Click email verification link to start using CNC");
        } else {
            NSLog(@"Failed to register email with error %@", error);
        }
    }];
    

    To register a customer using an email address, use the registerCustomerWithEmail method. If no error is returned the customer will receive a verification email which can be used to verify their account.

    Using Username/password

    // Using username/password
    SpotzCNCCustomerSDK.shared().registerCustomerWithUsername("customeremail@localz.com", password: "password", otherParameters: nil) { (error) -> Void in
        if (error == nil) {
            print("Registered!")
        } else {
            print("Failed to register username with error \(error)")
        }
    }
    
    // Using username/password
    [[SpotzCNCCustomerSDK shared] registerCustomerWithUsername:@"customeremail@localz.com" password:@"password" otherParameters:nil completion:^(NSError *error) {
    
        if (!error) {
            NSLog(@"Registered!");
        } else {
            NSLog(@"Failed to register username with error %@", error);
        }
    }];
    

    Register customer via username/password.

    2. Login a Customer

    SpotzCNCCustomerSDK.shared().loginCustomerWithUsername("customeremail@localz.com", password: "password") { (error) -> Void in
        if (error == nil) {
            print("Registered (or logged in)!")
        } else {
            print("Failed to register username with error \(error)")
        }
    }
    
    [[SpotzCNCCustomerSDK shared] loginCustomerWithUsername:@"customeremail@localz.com" password:@"password" completion:^(NSError *error) {
        if (!error) {
            NSLog(@"Customer logged in");
        } else {
            NSLog(@"Failed to login customer");
        }
    }
    

    Login existing customers using the loginCustomerWithUsername method and provide a username and password string in the arguments. If no error is returned the customer will be logged in.

    Orders

    A customer must be registered and logged in before performing any order methods.

    1. Create order

    // Example order attributes. Other are available by inspecting the SpotzCNCOrder header file.
    let order = SpotzCNCOrder(data: ["orderNumber":"000000000", "name":"Order ONE", "selectedPickupId":"myBranchId"])
    let branchId = "100"
    
    // Creates an order - Ensure customer is registered (and logged in) before calling this method.
    
    SpotzCNCCustomerSDK.shared().createOrder(order, branchId: branchId) { (error) -> Void in
        if let error = error {
            print("Failed to create order with error \(error)")
            return
        }
    
        print("Order created")
    }
    
    // Example order attributes. Other are available by inspecting the SpotzCNCOrder header file.
    SpotzCNCOrder *order = [SpotzCNCOrder initWithData:@{@"orderNumber":@"000000000", @"name":@"Order ONE", @"selectedPickupId":@"myBranchId"}];
    NSString *branchId = @"100";
    
    // Creates an order - Ensure customer is registered (and logged in) before calling this method.
    
    [[SpotzCNCCustomerSDK shared] createOrder:order branchId:branchId completion:^(NSError *error) {
        if (!error) {
            NSLog(@"Order created");
        } else {
            NSLog(@"Failed to create order with error %@", error);
        }
    }];
    

    Use the createOrder method to create an order. In the example, createOrder takes a SpotzCNCOrder object and a branchId string. If no errors are returned, the order has been successfully created.

    2. Retrieve non-completed orders for a customer

    SpotzCNCCustomerSDK.shared().getCustomerNonCompletedOrdersSpotRecheck(false) { (orders:[SpotzCNCOrder]!, error:NSError!) -> Void in
    
        if (error == nil) {
            // Do something with the customer's orders
        } else {
            print("Failed to get orders with error \(error)")
        }
    }
    
    [[SpotzCNCCustomerSDK shared] getCustomerNonCompletedOrdersSpotRecheck:false completion:^(NSArray *orders, NSError *error) {
    
        if (!error) {
            // Do something with the customer's orders
        } else {
            NSLog(@"Failed to get orders with error %@", error);
        }
    }];
    

    Add the following method to get an array non-completed orders, in the SpotzCNCOrder type, for a customer.

    2a. Add a comment to an order

    This is only relevant for usecases where a customer is leaving a comment on an order for a delivery.

    SpotzCNCCustomerSDK.shared().addCommentsToOrder(orderNumber, comments:"Example comment") { (error:NSError?) -> Void in
        if let error = error {
            // Successfully left comment on order
        } else {
            print("Failed to leave a comment on the order \(error)")
        }
    }
    
    [[SpotzCNCCustomerSDK shared] addCommentsToOrder:orderNumber comments:@"Example comment" completion:^(NSError *error) {
        if (!error) {
            // Successfully left comment on order
        } else {
            NSLog(@"Failed leave a comment on the order %@", error);
        }
    }];
    

    A comment may be added to an order when it is in one of the following order statuses:

    A specific order status can be supplied to the method in which case a comment will only successfully be left if the order is in that status.

    3. Check-in a customer order

    let order:SpotzCNCOrder! = /*Order should come from getCustomerNonCompletedOrdersSpotRecheck:completion:*/
    
    SpotzCNCCustomerSDK.shared().checkinOrder(order, force: false) { (numOrdersCheckedIn:NSNumber!, error:NSError?) -> Void in
    
        if (error == nil) {
            if (numOrdersCheckedIn.intValue > 1) {
                print("Order (\(order.orderNumber)) and \(numOrdersCheckedIn) others checked in!")
            } else {
                print("Order (\(order.orderNumber)) checked in!")
            }
        } else {
            print("Failed to check in order \(order.orderNumber) with error \(error)")
        }
    }
    
    SpotzCNCOrder *order = /*Order should come from getCustomerNonCompletedOrdersSpotRecheck:completion:*/;
    
    [[SpotzCNCCustomerSDK shared] checkinOrder:order force:true completion:^(NSNumber *numOrdersCheckedIn, NSError *error) {
    
        if (!error) {
            if (numOrdersCheckedIn.intValue > 1) {
                NSLog(@"Order (%@) and %i others checked in!", order.orderNumber, numOrdersCheckedIn.intValue-1);
            } else {
                NSLog(@"Order (%@) checked in!", order.orderNumber);
            }
        } else {
            NSLog(@"Failed to check in order %@ with %@", order.orderNumber, error);
        }
    }];
    

    Add the following method to check-in a customer order.

    3.1 Manual proximity triggers

    // An example of the proximityTriggers inside the order object:
    "proximityTriggers": [{
        "uiName": "Bay 1",
        "trigger": "_Screen25"
    },
    {
        "uiName": "Bay 2",
        "trigger": "_Screen26"
    }]
    
    let order = /*Order should come from getCustomerNonCompletedOrdersSpotRecheck:completion:*/
    
    // Check in order and on successful completion, update proximity order attribute.
    SpotzCNCCustomerSDK.shared().checkinOrder(order, force: false) { (numOrdersCheckedIn:NSNumber!, error:NSError!) -> Void in
        if let error = error {
            print("Failed to create order with error \(error)")
            return
        }
        else {
    
            let proximityAttribute:[AnyObject] = order!.proximityTriggers! as [AnyObject]
            var orderAttributeToUpdate: [String: String] = [:]
            if !proximityAttribute.isEmpty
            {
                // Say, we want to assign the first trigger value in the array
                orderAttributeToUpdate = proximityAttribute.first as! [String : String];
            }
             DispatchQueue.main.async {
                self.updateProximityAttribute(proximityAttribute: orderAttributeToUpdate["trigger"]! as NSString, order: order)
            }
         }
    }
    
    func updateProximityAttribute(proximityAttribute:NSString!, order:SpotzCNCOrder!) {
        SpotzCNCCustomerSDK.shared().updateOrderAttribute(proximityAttribute as String?, for:order) { (error) -> Void in
            if let error = error {
                print("Failed to update order attribute error \(error)")
                return
            }
            print("Proximity order attributed updated")
        }
    }
    
    // An example of the proximityTriggers inside the order object:
    @"proximityTriggers": @[@{
        @"uiName": @"Bay 1",
        @"trigger": @"_Screen25"
    },
    @{
        @"uiName": @"Bay 2",
        @"trigger": @"_Screen26"
    }]
    
    SpotzCNCOrder *order = /*Order should come from getCustomerNonCompletedOrdersSpotRecheck:completion:*/;
    
    // Check in order and on successful completion, update proximity order attribute.
    [[SpotzCNCCustomerSDK shared] checkinOrder:order force:false completion:^(NSNumber *numOrdersCheckedIn, NSError *error) {
        if (!error)
        {
            NSArray *proximityAttribute = order.proximityTriggers;
            NSDictionary *orderAttributeToUpdate = nil;
            if (proximityAttribute)
            {
                // Say, we want to assign the first trigger value in the array
                orderAttributeToUpdate = proximityAttribute[0];
            }
            dispatch_async(dispatch_get_main_queue(), ^{
                [self updateProximityAttribute:orderAttributeToUpdate[@"trigger"] forOrder:order];
            });
        }
    }];
    
    - (void)updateProximityAttribute:(NSString *)proximityAttribute forOrder:(SpotzCNCOrder *)order
    {
        [[SpotzCNCCustomerSDK shared] updateOrderAttribute:proximityAttribute forOrder:order completion:^(NSError *error) {
            if (!error) {
                NSLog(@"Updated order attribute, error? %@ ", error);
            }
        }];
    }
    

    Spotz SDK is used to report location events. Reporting occurs without user interaction. These reports can update details of the order when configured correctly in Spotz Console. However, sometimes it is desirable for customer explicitly report location (geo or otherwise). In this case, project or location can be configured with proximityTriggers. Customer SDK receives proximityTriggers in response from get order API call (see Retrieve non-completed orders for a customer).

    In this example, customer application would present to customer with buttons: Bay 1 and Bay 2. When customer presses either of these buttons, the customer application will need to call method to set order's attribute. Third parameter attribute must be set to the value of trigger attribute that corresponds to the uiName. For example for uiName Bay 2, attribute must be _Screen26.

    As customer application sets the attribute, it is important for the application to know whether the attribute has previously been set.

    4. Delete an order

    
    // To delete an order. Ensure customer is registered (and logged in) before calling this method.
    
    SpotzCNCCustomerSDK.shared().deleteOrderNumber("10000000") { (error) -> Void in
        if let error = error {
            print("Failed to delete order with error \(error)")
            return
        }
    
        print("Order deleted")
    }
    
    
    // To delete an order. Ensure customer is registered (and logged in) before calling this method.
    
    [[SpotzCNCCustomerSDK shared] deleteOrderNumber:@"10000000" completion:^(NSError *error) {
        if (!error) {
            NSLog(@"Order deleted");
        } else {
            NSLog(@"Failed to delete order with error %@", error);
        }
    }];
    

    Use the deleteOrderNumber method with an orderId string to delete an order. If there are no errors returned, the order has been deleted.

    5. Customer Feedback

    let feedbackComment = "Very good";
    let responsiveness = 5;
    let friendliness = 5;
    let usefulness = 5;
    let satisfaction = 5;
    let orderNumber = "MT456_098"
    
    SpotzCNCCustomerSDK.shared().giveFeedbackComment(feedbackComment, responsiveness: responsiveness, friendliness: friendliness, usefulness: usefulness, satisfaction: satisfaction, orderNumber: orderNumber) { (error) -> Void in
        if let error = error {
            print("Failed to provide feedback with error \(error)")
            return
        }
    
        print("Feedback received")
    }
    
    
    NSString *feedbackComment = @"Very good";
    NSNumber *responsiveness = @5;
    NSNumber *friendliness = @5;
    NSNumber *usefulness = @5;
    NSNumber *satisfaction = @5;
    NSString *orderNumber = @"MT456_098"
    
    [[SpotzCNCCustomerSDK shared] giveFeedbackComment:feedbackComment responsiveness:responsiveness friendliness:friendliness usefulness:usefulness satisfaction:satisfaction orderNumber:orderNumber completion:^(NSError *error) {
        if(error)
        {
            NSLog(@"Failed to provide feedback with error %@", error);
        }
    }];
    

    Use the giveFeedbackComment method to give customer an opportunity to provide feedback when an order is complete.

    When server side push message is received with action: feedback, you can choose to give the customer an opportunity to provide feedback via the following method.

    Notifications

    1. Push Notifications

    
    // Include the below CNC delegate methods to register and receive local and remote push notifications successfully.
    
    func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
    
        SpotzCNCCustomerSDK.shared().applicationDidRegisterForRemoteNotificationsWithDeviceToken(deviceToken)
    }
    
    func application(_ application: UIApplication, didFailToRegisterForRemoteNotificationsWithError error: Error) {
    
        SpotzCNCCustomerSDK.shared().applicationDidFailToRegisterForRemoteNotificationsWithError(error)
    }
    
    func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any], fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) {
    
        SpotzCNCCustomerSDK.shared().applicationDidReceiveRemoteNotification(userInfo, applicationState:application.applicationState, fetchCompletionHandler:completionHandler)
    }
    
    // Pre-iOS 10 only
    func application(_ application: UIApplication, didRegister notificationSettings: UIUserNotificationSettings) {
    
        SpotzCNCCustomerSDK.shared().applicationDidRegisterUserNotificationSettings(notificationSettings)
    }
    
    // Pre-iOS 10 only
    func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any]) {
    
        SpotzCNCCustomerSDK.shared().applicationDidReceiveRemoteNotification(userInfo applicationState:application.applicationState)
    }
    
    
    // Include the below CNC delegate methods to register and receive local and remote push notifications successfully.
    
    - (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken {
    
        [[SpotzCNCCustomerSDK shared] applicationDidRegisterForRemoteNotificationsWithDeviceToken:deviceToken];
    }
    
    - (void)application:(UIApplication *)application didFailToRegisterForRemoteNotificationsWithError:(NSError *)error {
    
        [[SpotzCNCCustomerSDK shared] applicationDidFailToRegisterForRemoteNotificationsWithError:error];
    }
    
    - (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler {
    
        [[SpotzCNCCustomerSDK shared] applicationDidReceiveRemoteNotification:userInfo applicationState:application.applicationState fetchCompletionHandler:completionHandler];
    }
    
    // Pre-iOS 10 only
    - (void)application:(UIApplication *)application didRegisterUserNotificationSettings:(UIUserNotificationSettings *)notificationSettings {
    
        [[SpotzCNCCustomerSDK shared] applicationDidRegisterUserNotificationSettings:notificationSettings];
    }
    
    // Pre-iOS 10 only
    - (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo {
    
        [[SpotzCNCCustomerSDK shared] applicationDidReceiveRemoteNotification:userInfo applicationState:application.applicationState];
    }
    

    Use the Localz Collections platform to notify the customer about important changes to the order.

    The text for the push notifications can be configured via Spotz Console.

    To handle these notifications please ensure the SDKs accompanying methods are also called.

    These include:

    2. Local Notifications

    func testNotification() {
        // Initialise a notification object. Title and body are optional here
        let notification = SpotzCNCNotification(withRequestId: "notification", title: "My Title", body: "My Body")
        // Add additional notification attributes
        notification.categoryIdentifier = "CheckinCategory"
        notification.userInfo = [
            "orderNumber":"1234"
        ]
        // Present the notification directly to the user
        notification.actionIdentifier = "CheckinAction"
    }
    
    
    - (void)testNotification {
        // Initialise a notification object. Title and body are optional here
        SpotzCNCNotification *notification = [[SpotzCNCNotification alloc] initWithRequestId:@"notification" title:@"My Title" body:@"My Body"];
        // Add additional notification attributes
        notification.categoryIdentifier = @"CheckInCategory";
        notification.userInfo = @{
            @"orderNumber":@"1234"
        };
        notification.actionIdentifier = @"CheckInAction";
        // Present the notification directly to the user
        [[SpotzCNCCustomerSDK shared] presentLocalNotification:notification];
    }
    
    
    func application(_ application: UIApplication, handleActionWithIdentifier identifier: String?, forRemoteNotification userInfo: [AnyHashable : Any], completionHandler: @escaping () -> Void) {
    
        SpotzCNCCustomerSDK.shared().applicationHandleActionWithIdentifier(identifier forLocalNotification:notification completionHandler:completionHandler)
    }
    
    // iOS 10 and greater
    func didReceive(_ response: UNNotificationResponse, completionHandler completion: @escaping (UNNotificationContentExtensionResponseOption) -> Void) {
    
        SpotzCNCCustomerSDK.shared().userNotificationCenterDidReceiveNotificationResponse(response withCompletionHandler:completionHandler)
    }
    
    
    // Pre-iOS 10 only
    - (void)application:(UIApplication *)application handleActionWithIdentifier:(NSString *)identifier forLocalNotification:(UILocalNotification *)notification completionHandler:(void (^)())completionHandler {
    
        [[SpotzCNCCustomerSDK shared] applicationHandleActionWithIdentifier:identifier forLocalNotification:notification completionHandler:completionHandler];
    }
    
    // iOS 10 and greater
    // NOTE: Requires `[UNUserNotificationCenter currentNotificationCenter].delegate = self;` to be set after calling `[[SpotzCNCCustomerSDK shared] startNotificationServices];`
    - (void)userNotificationCenter:(UNUserNotificationCenter *)center didReceiveNotificationResponse:(UNNotificationResponse *)response withCompletionHandler:(void (^)(void))completionHandler {
    
        [[SpotzCNCCustomerSDK shared] userNotificationCenterDidReceiveNotificationResponse:response withCompletionHandler:completionHandler];
    }
    
    // Datasource method to provide the number of custom actions
    func spotzCNCSDKNotificationNumberOfActions() -> Int32 {
        return 2;
    }
    
    // Datasource method to provide the custom titles for the custom actions
    func spotzCNCSDKNotificationActionTitle(for index: Int32) -> String! {
        var title = ""
        switch index {
            case 0:
                title = "Check-in Now"
            case 1:
                title = "Check-in later"
        }
        return title
    }
    
    // Delegate method to perform respective functions on the action tap of the local notification.
    func spotzCNCSDKNotificationDidSelectAction(at index: Int32, order: SpotzCNCOrder!) {
    
        let notification = SpotzCNCNotification(withRequestId: "CheckInNotification")
    
        switch index {
            case 0:
                SpotzCNCCustomerSDK.shared().checkinOrder(order, force: false) { (numOrdersCheckedIn, error) in
                    print("Order checked in")
                }
                notification.body = "Your order has been checked in"
            case 1:
                notification.body = "Let us know when you are on your way"
        }
    
        SpotzCNCCustomerSDK.shared().presentLocalNotification(notification)
    }
    
    // Datasource method to provide the number of custom actions
    - (int)spotzCNCSDKNotificationNumberOfActions
    {
        return 2;
    }
    
    // Datasource method to provide the custom titles for the custom actions
    - (NSString *)spotzCNCSDKNotificationActionTitleForIndex:(int)index
    {
        NSString *title = nil;
        switch (index) {
            case 0:
                title = @"Check-in Now";
                break;
            case 1:
                title = @"Check-in later";
                break;
    
            default:
                break;
        }
        return title;
    }
    
    // Delegate method to perform respective functions on the action tap of the local notification.
    - (void)spotzCNCSDKNotificationDidSelectActionAtIndex:(int)index order:(SpotzCNCOrder *)order
    {
        SpotzCNCNotification *notification = [[SpotzCNCNotification alloc] initWithRequestId:@"CheckInNotification"];
    
        switch (index) {
            case 0:
                [[SpotzCNCCustomerSDK shared] checkinOrder:order force:false completion:^(NSNumber *numOrdersCheckedIn, NSError *error) {
                    NSLog(@"Order checked in");
                }];
                notification.body = @"Your order has been checked in";
                break;
            case 1:
                notification.body = @"Let us know when you are on your way";
                break;
            default:
                break;
        }
    
        [[SpotzCNCCustomerSDK shared] presentLocalNotification:notification];
    }
    

    You can now set custom actions to the local notifications by calling new datasource and delegate methods.

    To trigger a local notification, use the presentLocalNotification method.

    To understand the location notification flow please refer to the diagrams:

    Click&Collect customer local notification flow

    License

    Copyright 2019 Localz Pty Ltd