Nodle Documentation
  • Introduction
  • Vision and Mission
  • Nodle IoT
  • Nodle App
  • Nodle Client
  • Nodle Portal
  • NODL Token
  • NFT Minting Tool
  • Nodle Explorer
  • Participate
  • Subquery Indexer
  • Nodle APIs
  • Nodle Parachain
  • Parachain Modules
  • Nodle SDK
  • Nodle Android SDK
  • Nodle iOS SDK
  • Smart Missions
  • Appendix
  • Glossary
Nodle Documentation
Nodle Documentation
Nodle iOS SDK

Nodle iOS SDK

Getting Started

IntroductionIntroductionVision and MissionVision and Mission

For Users

Nodle IoTNodle IoTNodle AppNodle AppNodle ClientNodle ClientNodle on zkSync EraNodle on zkSync EraNodle PortalNodle PortalNODL TokenNODL TokenNodle ExplorerNodle ExplorerParticipateParticipate

For Developers

SubQuery IndexerSubQuery IndexerNodle APIsNodle APIsNodle SDKNodle SDKNodle Android SDKNodle Android SDKNodle iOS SDKNodle iOS SDKSmart MissionsSmart Missions

More Info

AppendixAppendixGlossaryGlossary

iOS SDK Integration

Integrating the Nodle SDK into your iOS app is easy and straightforward.

  1. Generate Developer Key
    • Go and Create a Nodle account
    • Make sure you save your private key!
    • Copy your public_key from the extension
    • Proceed with the next steps
  2. Install the SDK
    1. Install the SDK via CocoaPods. If you don't have an existing Podfile, run pod init in your project directory. Add the following to your Podfile:

    2. NodleSDK
    3. Swift

      pod 'NodleSDK', :git => 'https://github.com/NodleCode/NodleSDK-Release'

    4. NodleSDK - Fetching specific version
    5. Swift

      pod 'NodleSDK', :git => 'https://github.com/NodleCode/NodleSDK-Release', :branch => 'main', :tag => '0.0.21'

    6. NodleSDK without CoreBluetooth
    7. Swift

      pod 'NodleSDKWCB', :podspec => 'https://raw.githubusercontent.com/NodleCode/NodleSDK-Release/main/NodleSDKWCB.podspec'

    8. NodleSDK - Fetching specific version - XCode 15
    9. Swift

      pod 'NodleSDK', :git => 'https://github.com/NodleCode/NodleSDK-Release', :branch => 'night', :tag => '0.0.23-night'

    10. NodleSDK - Fetching specific version - XCode 16
    11. Swift

      pod 'NodleSDK', :git => 'https://github.com/NodleCode/NodleSDK-Release', :branch => 'night', :tag => '0.0.24-night'

    12. NodleSDK without CoreBluetooth - XCode 16
    13. Swift

      pod 'NodleSDKWCB', :podspec => 'https://raw.githubusercontent.com/NodleCode/NodleSDK-Release/night/NodleSDKWCB.podspec'

      The latest version of the SDK is 0.0.24-night We recommend to add the following dependency which should be automatically pulled but if you encounter any issues you can add them to your Podfile like this:

      Pods for NodleSDK
      pod 'SQLite.swift', '~> 0.15.3'
      pod 'SwiftCBOR', '~> 0.4.5'
      pod 'SwiftProtobuf', '~> 1.26.0'

      Then, run pod install. You may also need to run pod install --repo-update .

    14. Add the SDK manually:
    15. You can also add the SDK to your project manually. Download the current release, unzip the package, and drag the version of the SDK that you want use for example the version with CoreBluetooth NodleSDK.xcframework into your Xcode project. It will automatically appear in the Frameworks, Libraries, and Embedded Content section of your target settings. Switch Do Not Embed to Embed & Sign. We recommend to add the following dependency which should be automatically pulled but if you encounter any issues you can add them to your Podfile like this:

      Pods for NodleSDK
      pod 'SQLite.swift', '~> 0.15.3'
      pod 'SwiftCBOR', '~> 0.4.5'
      pod 'SwiftProtobuf', '~> 1.26.0'

      Then, run pod install. You may also need to run pod repo update. If you run into trouble with pod please install cocoapods-deintegrate and run pod deintegrate and also you would need to remove your cache we recommend you do the following:

      rm -rf ~/Library/Caches/CocoaPods; rm -rf Pods; rm -rf ~/Library/Developer/Xcode/DerivedData/*; pod deintegrate;

      Then make sure you are using one of the latest cocoapods versions 1.11+ due to issues with cocoapods not picking dependency properly you need to set the following script on top of your Podfile. You can find example Podfile below:

      You could do the same manually by adding the ['BUILD_LIBRARY_FOR_DISTRIBUTION'] = 'YES' to your Pod project settings. If you are on older version of cocoapods before 1.9- you will not need to do anything and you can simply proceed to next steps.

    16. NodleSDK issues with dependencies:
    17. If you are experiencing issues please make sure the correct version of the dependencies are in your Podfile.lock as an example with our latest version of the dependencies found here NodleSDK 0.0.23-night and above:

      SQLite.swift: 8d054987f02728cc912b0eb5a9659650573a65a2
      SwiftCBOR: ac340b74d3b2cf1f8884bb748bd09875848e3873
      SwiftProtobuf: 5e8349171e7c2f88f5b9e683cb3cb79d1dc780b3

      If you are having trouble with the dependencies loading for older versions of our SDK please make sure they are corrected in the Podfile.lock file. After you have corrected them in the file to the correct versions and CHECKSUMS simply run pod install.

    18. NodleSDK requirements:
    19. We are currently using the following setup:

      cocoapods: 1.13+
      swift: 5+
      XCode: 15 and above
      build-system: New Build System
      ios: 13.0+

  3. Add the NodleSDK dependency: The SDK depends on Apple's CoreLocation, CoreBluetooth framework. In your target settings, go to General > Frameworks, Libraries, and Embedded Content and add CoreLocation, CoreBluetooth if you haven't already. If you are using the build without CoreBluetooth you will need to add only CoreLocation
  4. Initialize the Nodle SDK: You need to init the NodleSDK in your AppDelegate like below:
    • Swift
    • import UIKit
      import SwiftCBOR
      import SwiftProtobuf
      import NodleSDK
      import SQLite
      import CoreLocation
      import CoreBluetooth
      @main
      class AppDelegate: UIResponder, UIApplicationDelegate {
      let nodle = Nodle.sharedInstance
      func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
          return true
      }
      }

      Or you can initialize the NodleSDK in your ViewController like below:

    • Swift
    • import UIKit
      import SwiftCBOR
      import SwiftProtobuf
      import NodleSDK
      import SQLite
      import CoreLocation
      import CoreBluetooth
      class ViewController: UIViewController, CLLocationManagerDelegate, CBCentralManagerDelegate {
      private let locationManager = CLLocationManager()
      var centralManager: CBCentralManager?
      let nodle = Nodle.sharedInstance
      }

      Then you can proceed to next steps below. Please make sure that you have added and request all permissions and dependency before you run the SDK.

  5. Request Permissions: Before requesting permissions, you must add location usage strings to your Info.plist file. We require a couple permissions and they have to be added like below:
    1. Here is a small example how it should look like when configured:

      image

      The NodleSDK require Bluetooth and Location permissions to be added before it is started. The NodleSDKWCB doesn't require Bluetooth. Then you can proceed to next step and request permissions for Location and Bluetooth via one of the two approaches listed below depending on your choice:

    2. Request permissions manually for NodleSDK without any third party:
    3. Request permissions manually for NodleSDKWCB without any third party:
    4. Request permissions via third party - SPPermissions
    5. We recommend the SPPermissions third party library to request permissions:

      Please follow their guide how to install and setup the request. After permissions are requested and given the NodleSDK should work as expected.

      image
  6. Run the Nodle SDK: In the AppDelegate or ViewController you can start Nodle by giving it your public key in the following format ss58:public_key generated in Step 1:
  • Swift

Nodle().start("ss58:public_key")

You can find more info here: Nodle SDK - iOS API and Configuration

And there you have it! You’re good to go!

Run Nodle SDK in Background (Optional)

With our latest update NodleSDK is able to perform background scanning. In order to work please make sure to allowAlwaysAuthorization for background permissions and Background Modes. Then the SDK will then be working in the background for you. You can chose one of the modes that you would want to adopt or you can disable it. Depending on the permissions that are allowed the SDK will be able to perform different actions in each of the modes.

Enabling background modes - required

The NodleSDK requires certain Background Modes to be enabled in order to perform background scanning. Here is example of the ones you need to enable:

image

Please head out to our configuration page here: Nodle SDK - iOS API and Configuration You have successfully configured the NodleSDK to perform background scanning.

Generate Privacy Report - XCode 15 support

With the latest version of XCode 15 and our SDK, we have a Privacy manifest generated automatically for you with all the required information that the SDK uses and needs to function properly. Here is a sample version of the report:

image

To generate the report, select Product -> Archive -> Right-click on your build and then select Generate Privacy Report. You should see all the entries like above image. Our SDK doesn't use any of the items in the report for anything else than app functionality. The SDK doesn't have any tracking domains that have been used.

Signing Requirements for Third Party SDK - XCode 15

With the latest version of XCode 15 and our SDK, we will have all future versions of the SDK signed with our identity, and Apple as authority to validate the SDK. The status of the SDK should be as below:

image

While our SDK isn't identified as privacy impacting, we want to take advantage of Apple’s new strategy for validating SDK authors. The future new versions will be always signed and with the correct identity as Nodle Technology. Please make sure to report anything suspicious when integrating our SDK.

Checking Your SDK Rewards

Currently we have our dashboard under development and rewards are not available. If you want see your rewards please go to our Nodle Subscan please follow the steps:

  1. Copy your public_key and paste it in the search bar
  2. Slide down the page after it loads and head to allocations
  3. You should see you rewards which are allocated every 2 hours.
  4. image

ℹ️
Make sure to add all permissions to the SDK in order to see your rewards. We have a lot of traffic so please bear with us since rewards might take a bit of time.

If you allow all the rules in SDK you should see the packets coming to the dashboard. Then rewards should be visible.

SDK Configuration

The SDK receives configuration remotely from Nodle servers as well as statically using API calls. The static configuration always takes precedence over the remote configuration.

Nodle SDK API

To interact with the SDK you need to call the Nodle.sharedInstance method that will give you an Instance of the INodle class. The following are all the public methods for the Nodle API.

Swift

import UIKit
import SwiftCBOR
import SwiftProtobuf
import NodleSDK
import SQLite
import CoreLocation
import CoreBluetooth
let nodle = Nodle.sharedInstance

start

public func start(public_key: String)

Immediately starts the Nodle SDK

Parameters
public_key
The application public_key created in Step 1

Example:

Swift

Nodle().start("ss58:public_key")

isStarted

public func isStarted() -> Bool

Checks if the Nodle SDK is started

Parameters
boolean
true if the Nodle SDK is started, false otherwise

Example:

Swift

let sdkStarted = Nodle().isStarted()

isScanning

public func isScanning() -> Bool

Checks if the Nodle SDK is currently scanning the BLE neighborhood. This is useful if you want to show that the SDK is working.

Parameters
boolean
true if the Nodle SDK is scanning, false otherwise

Example:

Swift

let sdkScanning = Nodle().isScanning()

stop

public func stop()

Immediately stops the Nodle SDK

Example:

Swift

Nodle().stop()

clear

public func clear()

Clear any configs by Nodle SDK

Example:

Swift

Nodle().clear()

getVersion

public func getVersion() -> String

Get the version identifier of the Nodle SDK.

Parameters
String
the current version of the Nodle SDK

Example:

Swift

let nodleSdkVersion = Nodle().getVersion()

getEvents

public func getEvents() -> NodleEvent

Get the raw bluetooth events from the Nodle SDK with the following type:

Returns
NodleEventType.BlePayloadEvent
Returns NodleBluetoothScanRecord
NodleEventType.BleStartSearching
Returns NodleBluetoothEvent
NodleEventType.BleStopSearching
Returns NodleBluetoothEvent
NodleEventType.BeaconPayloadEvent
Returns NodleBeaconScanRecord
NodleEventType.BeaconStartSearching
Returns NodleBeaconEvent
NodleEventType.BeaconStopSearching
Returns NodleBeaconEvent

Example of available return event classes below:

Returns
NodleBluetoothScanRecord
Raw Bluetooth Record from Nodle SDK
NodleBluetoothEvent
Bluetooth Event when the SDK start/stop
NodleBeaconScanRecord
Raw Beacon Record from Nodle SDK
NodleBeaconEvent
Beacon Event when the SDK start/stop

Example:

NodleSDK - Swift

NodleSDKWCB - Swift

The following data can be collected from the NodleEventType:

Key
Description
Default Value
type
returns nodle bluetooth event type
NodleEventType

The following data can be collected from the NodleBluetoothScanRecord:

Key
Description
Default Value
device
returns device unique identifier
String
rssi
returns received signal strength indicator
Int
bytes
returns raw bytes of the record
[UInt8]
manufacturerSpecificData
returns the manufacturer specific data associated with the manufacturer id
[Int : [UInt8]]
servicesUuids
returns an array of services UUID's within the advertisement
Array<CBUUID>

The following data can be collected from the NodleBluetoothEvent:

Key
Description
Default Value
scanning
returns bluetooth scanning state
Bool

The following data can be collected from the NodleBeaconScanRecord:

Key
Description
Default Value
identifier
returns device unique identifier
String
major
returns major value of the beacon
NSNumber
minor
returns minor value of the beacon
NSNumber
proximity
returns proximity value of the beacon
Int
accuracy
returns accuracy value of the beacon
Double
rssi
returns received signal strength value of the beacon
Int

The following data can be collected from the NodleBeaconEvent:

Key
Description
Default Value
scanning
returns beacon scanning state
Bool

The table shows rational range for the beacon devices that are found:

Key
Description
Range
proximity
Int
unknown = 0, immediate = 1, near = 2, far = 3
accuracy
Double
unknown 0, 0 - 0.5 immediate, 0.5 - 3 near, 3+ far in meters
rssi
Int
-128

registerNodleBackgroundTask

public func registerNodleBackgroundTask()

Register the Nodle SDK background task

Example:

Swift

Nodle().registerNodleBackgroundTask()

scheduleNodleBackgroundTask

public func scheduleNodleBackgroundTask()

Schedules the Nodle SDK background task

Example:

Swift

Nodle().scheduleNodleBackgroundTask()

config

public func config(path: Path)

public func <T> config(key: String, value: T)

configure the SDK either by supplying a json file located in ../config.json or by directly configuring a key. An example of a json configuration look like this:

{
"ble": {
"scan": {
"duration-msec": 10000,
"interval-msec": 90000,
"interval-x-factor": 1
}
},
"dtn": {
"use-cellular": false
}
}

The following are the table of all the keys available and their description:

Key
Description
Default Value
ble.scan.duration-msec
duration of a single ble pass in milliseconds. Longer scan increase battery consumption but gives more reward.
10000
ble.scan.interval-msec
wait time between two ble pass in milliseconds. Longer period reduce battery consumption but gives less reward
90000
ble.scan.interval-x-factor
multiplier for the ble scan interval above.
1
dtn.use-cellular
if true, the cellular connexion will be used. if false, only wifi connection will be used.
true
cron.ios-bg-mode
If specified, the SDK will run in the specific background mode that it is selected.
2
cron.ios-bg-mode-distance-meters
If specified, the SDK will trigger background scans for Normal mode depending on the meters that are specified with this option.
20
cron.ios-infinite-scan
if true, the WCB SDK will perform infinite Beacon scanning. If false the WCB SDK won't perform infinite Beacon scannning.
false

there is another table that will allow you to configure our SDK background modes. There are 4 available modes: NONE, ECO, NORMAL, AGGRESSIVE for the NodleSDK please check them in the table below:

Key
Description
Default Value
NONE
The SDK will run in foreground mode only. You don't need to give allowAlways permissions. WhileInUse is enough for this mode. You may wish to only use Background Tasks for this mode.
0
AGGRESSIVE
The SDK will run in aggressive mode that require all permissions we requested to allowAlways. Then you have to enable Background Modes as well. There is no need to register Background Tasks for this mode. This mode will work even when the phone is with locked screen. This mode will keep the SDK awake without suspending it. Once terminated it won't be able to restore it.
1
NORMAL
The SDK will run in normal mode that require all permissions we requested to allowAlways since it still runs in the background. Then you have to enable Background Modes as well. This mode will be a bit less aggressive than the previous mode. It will trigger when there are location changes. You can change the distance with the config option. You may wish to combine Background Tasks for this mode. This mode will work even when the phone is with locked screen. This mode will be able to awake the SDK after it's fully suspended. Once terminated it won't be able to restore it.
2
ECO
The SDK will run in eco mode that require all permissions we requested to allowAlways since it still runs in the background. Then you have to enable Background Modes as well. This mode will provide a very limited background work. It will trigger really rarely in the background. And when there are location changes. You may wish to combine Background Tasks for this mode. This mode will work even when the phone is with locked screen. This mode will be able to awake the SDK after it's fully suspended and even terminated.
3

Example:

Swift

Debug Logs API

This API enable the debug logs for the SDK and allows developer to debug on their own and have better visiblity on their application. The default value will be false which will output PRODUCTION level logs going forward. Here is a sample how to enable/disable the API:

nodle.config(key: "core.debug-log.enable", value: false)

Production Logs

  • Init of the SDK
  • Dispatcher event logs from the API
  • SDKCore logs
    • init of the core
    • SDK ID
  • Feature logs
    • Bluetooth Scanner lifecycle logs
      • enabled/disabled
      • success scan log
      • failed scan log
    • Cell Scanner lifecycle logs
      • enabled/disabled
      • scan started
      • scan failed
    • Heartbeat feature logs
      • enabled/disabled

Debug Logs

  • Init of the SDK
  • Dispatcher event logs from the API
  • SDKCore logs
    • init of the core
    • current SDK setup dump
    • bundles in the DB
    • SDK ID
  • Feature logs
    • Bluetooth Scanner lifecycle logs
      • enabled/disabled
      • success scan log
      • each scan item found
      • transmission for bundle
      • failed scan log
    • Cell Scanner lifecycle logs
      • enabled/disabled
      • scan started
      • scan failed
      • transmission for bundle
    • Network feature logs
      • network status log
      • resume bundles logs
      • networking logs over CLA Http
      • networking bundle transmission logs
    • Heartbeat feature logs
      • enabled/disabled
      • transmission log
      • error logs
    • Location Provider logs
      • waiting for location log
      • saved location fetch log
      • timeout on location log
      • fresh location fetch log
      • error logs

Heartbeat API

public func getHeartbeats() -> Array<NodleHeartbeatRecord?>?

The following data can be collected from the NodleHeartbeatRecord each parameter is optional:

Key
Description
Default Value
id
returns hb unique identifier
Int64?
timestamp
returns the generated timestamp when created
UInt64?
timezone
returns the device timezone
String?
locationH3
returns the device last known location in h3 format string
String?
geoHash
returns the device last known location in geohash format
String?
isBlePermissionsGranted
returns the device ble permissions granted
Bool?
isLocPermissionsGranted
returns the device location permissions granted
Bool?
isWifiEnabled
returns the device wifi module status
Bool?
isCellEnabled
returns the device cell module status
Bool?
isBluetoothEnabled
returns the device bluetooth module status
Bool?
sdkVersion
returns the sdk version
String?
configVersion
returns the sdk config version
String?
os
returns the device os
String?
phone
returns the device model
String?
release
returns the device release
String?
api
returns the device api level
String?
hardware
returns the device hardware name
String?
appName
returns the app name
String?
battery
returns the device battery
Int?
charging
returns the device charging status
Bool?
appInForeground
returns the app current status
Bool?
phoneStorageTotal
returns the device total storage
String?
phoneStorageAvailable
returns the device storage available
String?
sdkStorage
returns the device storage consumed
String?
httpIn
returns the sdk http input
String?
httpOut
returns the sdk http output
String?
bundleRxCount
returns the DTN RX
Int?
bundleTxCount
returns the DTN TX
Int?
bleScanSuccess
returns the BLE Scan success count
Int?
bleScanFailed
returns the BLE Failed count
Int?
blePayloadCount
returns the BLE payload found
Int?
buildType
returns the buildType of the SDK
String?

The HB API will provide a history of the heartbeats being generated by the SDK. It will always add the latest HB on top of the list being sorted by the timestamp. When there is a new heartbeat it will take the 0 element in the array. Here is a sample how to increase/decrease the storage size and be able to fetch all the heartbeats:

nodle.config(key: "core.heartbeat.history", value: 100)

Swift

nodle.getHeartbeats()?.forEach { it in
print("Heartbeat: \(String(describing: it))")
}

H3 API

public func getH3() -> H3?

Return the H3 instance exposing the H3 library methods to be used by the developer:

Returns
H3
Returns H3Core

The H3 interface with all the methods that the developer can take advantage is defined below:

Method
Description
Return Value
h3IsValid(h3: Int64)
Returns true if the h3 index is valid
Bool
h3IsValid(h3Address: String)
Returns true if the h3 index is valid
Bool
h3GetBaseCell(h3: Int64)
Returns the base cell number for the index
Int
h3GetBaseCell(h3Address: String)
Returns the base cell number for the index
Int
h3IsPentagon(h3: Int64)
Returns true if this index is one of the twelve pentagons per resolution
Bool
h3IsPentagon(h3Address: String)
Returns true if this index is one of the twelve pentagons per resolution
Bool
geoToH3(lat: Double, lng: Double, res: Int)
Find the H3 index of the resolution res cell containing the lat/lon (in degrees) returns h3 index
Int64
geoToH3Address(lat: Double, lng: Double, res: Int)
Find the H3 index of the resolution res cell containing the lat/lon (in degrees) returns H3 index
String
h3ToGeo(h3: Int64)
Find the latitude, longitude (both in degrees) center point of the cell.
(NodleLat, NodleLng)
h3ToGeo(h3Address: String)
Find the latitude, longitude (degrees) center point of the cell.
(NodleLat, NodleLng)
h3ToGeoBoundary(h3: Int64)
Find the cell boundary in latitude, longitude (degrees) coordinates for the cell
Array<(NodleLat, NodleLng)>
h3ToGeoBoundary(h3Address: String)
Find the cell boundary in latitude, longitude (degrees) coordinates for the cell
Array<(NodleLat, NodleLng)>
kRing(h3Address: String?, k: Int)
Neighboring indexes in all directions h3Address – Origin index k – Number of rings around the origin
Array<String?>?
kRing(h3: Int64, k: Int)
Neighboring indexes in all directions h3Address – Origin index k – Number of rings around the origin
Array<Int64>
h3Distance(a: String?, b: String?)
Returns the distance between a and b. This is the grid distance, or distance expressed in number of H3 cells.
Int
h3Distance(a: Int64, b: Int64)
Returns the distance between a and b. This is the grid distance, or distance expressed in number of H3 cells.
Int
h3Line(startAddress: String?, endAddress: String?)
Given two H3 indexes, return the line of indexes between them (inclusive of endpoints).
Array<String?>?
h3Line(start: Int64, end: Int64)
Given two H3 indexes, return the line of indexes between them (inclusive of endpoints).
Array<Int64>
h3GetResolution(h3Address: String?)
Returns the resolution of the provided index
Int
h3GetResolution(h3: Int64)
Returns the resolution of the provided index
Int
h3ToString(h3: Int64)
Converts from long representation of an index to String representation.
String?
stringToH3(h3Address: String?)
Converts from String representation of an index to long representation.
Int64
numHexagons(res: Int)
Returns the number of unique H3 indexes at resolution res.
Int64

Swift

nodle.getH3()?.h3ToGeo(h3Address: "8a1eebbb461ffff")

SDK Troubleshooting

In this section, we will try to explain some of the common issues you may face on Android and how to troubleshoot them.

General Guidelines

Here are some of the common steps to take in case of issues in general.

  1. Please make sure to follow all steps carefully and ensure have done all that's requested from you for the integration.
  2. Make sure you have selected the right version of the SDK with Google Play services or without depending on your usage.
  3. Make sure you have your public key in the following format ss58:public_key.
  4. Make sure you have all permissions in your Android manifest file and you have added your application class inside the android tag.
  5. Make sure you have initialized the NodleSDK.
  6. Make sure to start the NodleSDK.

If you are still having issues, proceed with the next steps below.

Bluetooth Troubleshooting

Follow these steps to troubleshoot issues with your Bluetooth.

  1. Please disable your Bluetooth, Wifi, Mobile Data and proceed to next step.
  2. Go to your phone Settings-> Apps -> Bluetooth. Clear the cache and data for the system application. Some manufacturers hide that so you might need to enable it to find it.
  3. After you have done the above, restart your phone.
  4. If you still having Bluetooth related problems, contact your manufacturer or update your software. If the issue persists, try with another phone from a different manufacturer.

Location Troubleshooting

To troubleshoot issues with location, do the following:

  1. Make sure you have Location enabled on your phone.
  2. Make sure you followed all steps on our documentation for the integration and you are requesting all the permissions in your Manifest.
  3. Make sure you are requesting all runtime permissions for the user and that you have permissions for them to be used. You can verify that on the next step.
  4. Go to your phone Settings-> Apps -> Your Application and make sure you have Location permission enabled. Location can be enabled either Always or While in Use.
  5. If you are still having issues, disable your Location, Wifi, Mobile data.
  6. After you have done the above, restart your phone.
  7. If you still having Location related problems, contact your manufacturer or update your software.
⚠️
Important: Please make sure you are using the right version of the SDK. If the issue persists, try with another phone from a different manufacturer.

Network Troubleshooting

Here are the steps to follow to troubleshoot issues with the network.

  1. Make sure you have Wifi or Mobile data enabled on your phone. We need this to be able to process data in our SDK.
  2. Make sure you have an internet connection (double check this). Also, check for weak connections. Our SDK will still keep any generated data on your phone until your connection is stable, so you aren't missing out.
  3. If you are having issues with either Wifi or Mobile data, go to your phone Settings-> Wifi / Mobile Data and make sure you have them enabled. If you have them enabled but still there’s no connection, follow the steps below.
    1. Go ahead and disable your Wifi, Mobile data.
    2. After you have done the above, restart your phone. If you’re still having internet related problems, contact your manufacturer or update your software.
  4. Once you have the internet connection, you can proceed.

Podfile Troubleshooting

Here’s how you can tackle common issues with Podfile:

  1. Make sure you have the latest version of Cocoapods installed. Each version has different scripts and performs differently. Also, dependency management and project structure is different.
  2. Follow each of the steps in our documentation and ensure you don’t skip anything.
  3. Make sure you generate the podfile correctly.
  4. During update, make sure to remove .lock file as well as the workspace that's generated.
  5. Perform pod install, which will generate a clear workspace for your project.
  6. Clear Cocoapods cache since they have a lot of local and remote issues. However, they are a valid option for dependency management.
  7. Make sure you are on the latest version of the SDK. You can see that from documentation page. This is to ensure optimum performance and issue resolution.

After all the above are done and you are still facing issues, please reach out to us or the Cocoapods team.

Changelog

In this page, you can find our latest releases and the changes that are being done in the new and old versions of the SDKs for iOS.

Version 0.0.24 (08.04.2025) - iOS SDK - Night branch

Updated

  • Added support for XCode 16
  • Updated security later and optimizations

Version 0.0.23 (07.06.2024) - iOS SDK - Night branch

Updated

  • Updated security later and optimizations

Version 0.0.22 (12.01.2024) - iOS SDK - Night branch

Added

  • Added XCode 15 support
  • Added Privacy manifest with all information required for the SDK
    • Added Privacy report generation for latest XCode versions
    • Added Signing the new versions of the SDK will always be signed going forward
    • Added better error handling around the SDK

Updated

  • Updated security layer to latest version
  • Updated documentation with latest required changes

Fixed

Fixed a URL RFC related issue from latest Apple update

Version 0.0.21 (01.08.2023) - iOS SDK

Added

  • Increased the overall stability of the SDK
  • Prevented false positive checks from the security layer that caused memory leaks
  • Prevented potential crash that happen from the memory leaks in the Bluetooth,Network layer
  • We have added Hotfixes around the codebase after we have received crash reports to improve stability on the following locations around the SDK:
    • Prevented a crash after the SDK performs a succesful scan and passing records to getEvents API
    • Prevented a crash where the Location Manager would receive bad location
    • Prevented a crash where our Beacon Scanner instance could be nullable before performing a scan
    • Prevented a crash on the condition where the permissions checks could be empty for our Beacon Manager
    • Prevented a potential crash where the Beacon payloads could be corrupted and still passed forward to the internals of the SDK
    • Prevented a crash where the beacon uuids could be invalid before starting/stopping monitoring
    • Prevented a crash where the beacon regions were in range
    • Prevented potential crash when receiving data from inbox/outbox in the Network layer
    • Prevented the SDK from crashing randomly by depracating the Background Task API
  • Awake API base
    • Allow the developer to be able to restart the NodleSDK after their application is being terminated by setup the following methods:
      • nodleLocationManager.restartNodleInTerminatedState { result in }
  • Infinite Scanning option
    • Allow the developer to be able to configure the WCB SDK in a way that will enable them to do infinite scan without the need for the manager to stop/start and do the SDK rotation by using the following method:
      • nodle.config(key: "cron.ios-infinite-scan", value: true)
  • HB API which can be used by developers to retrieve the last heartbeats that have been produced by their SDK:
    • nodle.config(key: "core.heartbeat.history", value: 100)
  • H3 API which can be used by developers to use the Uber H3 Library features safely
  • Debug Logs API that will allow the developers to debug their own SDK with two log levels PRODUCTION/DEBUG:
    • nodle.config(key: "core.debug-log.enable", value: true)
  • Improved and extented capabilities for background mode scanning which will improve the overall capabilities of the SDK and the network
  • Improved and extended capabilities for beacon scanning on CoreBluetooth variation of the SDK

Fixed

  • Fixed a issue with H3 causing buffer overflow for some swift runtimes
  • Fixed a issue where H3 was causing a heap use after free for some swift runtimes
  • Fixed a memory leaks caused by H3 module and swift runtimes
  • Fixed a memory leaks caused by the security layer in the H3 module
  • Fixed a memory leaks caused by the security layer in the Bluetooth, Network layer
  • Fixed a issue where the SDK won't update the last known location all the time

Updated

  • Security to latest version with last hardened protection mechanisms
  • Suspended AwakeAPI until the stability of the SDK is back on track
  • Update access modifiers for NodleLocationManager in order the developer to be able to init at application level and take advantage of the AwakeAPI
  • Update Beacon Scanner logic to be able to scan infinitely
  • Updated config so the developer can enable/disable the infinite scanning

Removed

  • We have deprecated the Background Task API due receiving crash reports from clients and minimum value that the API capabilities brought to the network

Version 0.0.16 (05.12.2022) - iOS SDK

Added

  • Added XCode 14 support
  • Added better error handling around the SDK

Updated

  • Updated security layer

Fixed

  • Fixed a critical issue with Location layer
  • Fixed issues with Network, Bluetooth, Config, DB, Location

Version 0.0.15 (26.09.2022) - iOS SDK

Added

  • Swift 5.7 support

Fixed

  • Fixed issues with background modes capabilities not being added by the developer
  • Fixed crashes in SDK Core initialization
  • Fixed crashes in Network, Bluetooth, Config, Location layer

Version 0.0.14 (11.07.2022) - iOS SDK

Added

  • Security updates

Fixed

  • Issues with background work
  • Issues with background modes
  • Issues with location providers
  • Issues with config
  • Issues with network

Removed

  • We are deprecating MacOS support and catalyst in the future versions of our SDK

Version 0.0.13 (12.04.2022) - iOS SDK

Added

  • Background capabilities
  • Background modes

Fixed

  • Performance improvements

Updated

  • Config options

Unity SDK Plugin

Integrating the Nodle SDK into your Unity app is easy and straightforward. You can use our NodleSDK Quickstart application or just follow the steps below and you should be ready to go in no time.

  1. Step 1: Generate Developer Key
    • Go and Create a Nodle account
    • Make sure you save your private key!
    • Copy your public_key from the extension
    • Proceed forward with next steps.
  2. Setup Developer Environments: Please make sure to follow our Android SDK and iOS SDK and configure your environement based on the requirements there.
  3. Create Unity Application: You can follow the steps to create a new project or skip below to just importing the plugin depending on your platform.
    1. Creating a new project - Android
      1. Please start by creating a new project Android in Unity Hub it is not required to use that template you can create a blank or 3D or other.
      2. image
      3. After you have created the project you should see the following:
      4. image
      5. Then proceed to switch the platform to Android go to File->Build Settings and select Android:
      6. image
      7. Next go ahead and click Switch platform. After switching you can go to next step to import the plugin.
    2. Creating a new project - iOS
      1. Please start by creating a new project iOS in Unity Hub it is not required to use that template you can create a blank or 3D or other.
      2. image
      3. After you have created the project you should see the following:
        1. image
      4. Then proceed to switch the platform to Android go to File->Build Settings and select iOS.
      5. image
      6. Next go ahead and click Switch platform. After switching you can go to next step to import the plugin.
  4. Updating Player Settings: You have to update your player settings for Android/iOS before you import the plugin.
    1. Player Settings - Android
      1. You have to set the player settings for you application and make sure to check the Custom Gradle Templates as shown in the picture. The minimum version for the SDK is Android 7. Please set that in Android -> Other Settings -> Minimum version when you change the player settings.
      2. image
      3. After you import the plugin then copy/merge the following files: baseProjectTemplate.gradle, gradleTemplate.properties, mainTemplate.gradle from Assets -> Plugins -> Nodle -> Android to Assets -> Plugins -> Android then copy the content of AndroidManifest.xml into your application manifest. Then proceed with next steps.
    2. Player Settings - iOS
      1. There are no changes for iOS except your player base settings to be set and you can proceed to next steps.
      2. image
  5. Import the Nodle Unity Plugin into your application: You can follow the steps to import the Nodle plugin depending on your platform into your application.
    1. Import the Nodle package - Android
      1. Start by selecting from Assets->Import Package-> Custom Package and then select the Nodle SDK package.
      2. image
      3. Import everything from the package. We recommend to import the Sample Scene too.
      4. image
      5. Import the TMP Essentials. If there is a problem with the buttons, please close and open the project there is a bug on Unity side.
      6. image
      7. Open the Sample Scene: Assets/Plugins/Nodle/SampleScene/SampleScene.unity.
      8. image
      9. Next, select the Main Camera object and in the inspector place your public_key with the following format: ss58:public_key
      10. image
      11. Then, go to Build Settings If you scene didn't appear, click on the Add Open Scenes, and place it as 0 (Drag the scene name to the top of the list). Build and Run!
      12. image
      13. That’s it! You can setup your Player Settings details from your application and run the NodleSDK.
    2. Import the Nodle package - iOS
      1. Start by selecting from Assets->Import Package-> Custom Package and then select the Nodle SDK package.
      2. image
      3. Next, please go ahead and import everything from the package. We recommend to import the Sample Scene too.
      4. image
      5. Next, open the Sample Scene located under Assets → Plugins → Nodle → Sample Scene
      6. image
      7. Import the TMP Essentials. If there is a problem with the buttons please close and open the project there is a bug on Unity side.
      8. image
      9. Next select the Main Camera object and in the inspector place your public_key with the following format: ss58:public_key
      10. image
      11. Then go to Build Settings. If your scene didn't appear, click on the Add Open Scenes, and place it as 0 (Drag the scene name to the top of the list). Build the project!
      12. image
      13. After making the build into a build folder. Copy the Podile from Plugins -> Nodle -> iOS -> NodleIOSPlugin -> XCodeFiles to the root of that build folder. Then open the build folder location in terminal and install the NodleSDK with the following command: pod install 
      14. You can go ahead and use the generated .workspace file from now on to run the project! Please make sure to add all permissions to your Info.plist before running the application. You can find how to do that here: NodleSDK Permissions.
💡
Note: There is no need to build more folders after the first build since all changes will remain even if you build again in the same location.

And there you have it! You’re good to go!

Checking Your SDK Rewards

Currently we have our dashboard under development and rewards are not available. If you want see your rewards please go to our Nodle Subscan please follow the steps:

  1. Copy your public_key and paste it in the search bar.
  2. Slide down the page after it loads and head to allocations.
  3. You should see you rewards which are allocated every 2 hours.
  4. image
⚠️
Important: Make sure to add all permissions to the SDK in order to see your rewards. We have a lot of traffic so please bear with us since rewards might take a bit of time.

If you allow all the rules in SDK, you should see the packets coming to the dashboard. Then, rewards should be visible.

← Previous

Nodle Android SDK

Next →

Smart Missions

On this page

  • iOS SDK Integration
  • Run Nodle SDK in Background (Optional)
  • Checking Your SDK Rewards
  • SDK Configuration
  • Nodle SDK API
  • start
  • isStarted
  • isScanning
  • stop
  • clear
  • getVersion
  • getEvents
  • registerNodleBackgroundTask
  • scheduleNodleBackgroundTask
  • config
  • Debug Logs API
  • Production Logs
  • Debug Logs
  • Heartbeat API
  • H3 API
  • SDK Troubleshooting
  • General Guidelines
  • Bluetooth Troubleshooting
  • Location Troubleshooting
  • Network Troubleshooting
  • Podfile Troubleshooting
  • Changelog
  • Unity SDK Plugin
  • Checking Your SDK Rewards
Logo

Nodle Website

Network Explorer

Chain Explorer

© Nodle, 2024

DiscordTelegramXYouTube
post_install do |installer|
installer.pods_project.targets.each do |target|
target.build_configurations.each do |config|
config.build_settings['BUILD_LIBRARY_FOR_DISTRIBUTION'] = 'YES'
end
end
end
# If any errors for example dyld: Symbol not found please use pod deintegrate and pod install again. You should remove your
# Podfile.lock and workspace and let cocoapods generate it for you if you are having
# trouble. Make sure you close and open the workspace when you are doing all above before
# pod install again.
platform :ios, '13.0'

# use_modular_headers!

target 'YourTarget' do
  # Comment the next line if you don't want to use dynamic frameworks
  use_frameworks!

  # Pods for TestApp
  pod 'NodleSDK'
  pod 'SQLite.swift', '~> 0.15.3'
  pod 'SwiftCBOR', '~> 0.4.5'
  pod 'SwiftProtobuf', '~> 1.26.0'

endYou could do the same manually by adding the ['BUILD_LIBRARY_FOR_DISTRIBUTION'] = 'YES' to your Pod project settings. If you are on older version of cocoapods before 1.9- you will not need to do anything and you can simply proceed to next steps.

NodleSDK issues with dependencies:
If you are experiencing issues please make sure the correct version of the dependencies are in your Podfile.lock as an example with our latest version of the dependencies found here NodleSDK 0.0.21:
// NodleSDK
NSBluetoothAlwaysUsageDescription - Need for our bluetooth scan
NSBluetoothPeripheralUsageDescription - Need for our bluetooth scan
NSLocationAlwaysUsageDescription - Need for our location request from the background
NSLocationAlwaysAndWhenInUseUsageDescription - Need for our location request from background
NSLocationWhenInUseUsageDescription - Need for our location request
NSLocationUsageDescription - Need to be able to perform additional changes to
location while in the background.
// NodleSDKWCB
NSLocationAlwaysUsageDescription - Need for our location request from the background
NSLocationAlwaysAndWhenInUseUsageDescription - Need for our location request from the background
NSLocationWhenInUseUsageDescription - Need for our location request
NSLocationUsageDescription - Need to be able to perform additional changes to
location while in the background.
import UIKit
import SwiftCBOR
import SwiftProtobuf
import NodleSDK
import SQLite
import CoreLocation
import CoreBluetooth
class ViewController: UIViewController, CLLocationManagerDelegate, CBCentralManagerDelegate {
private let locationManager = CLLocationManager()
var centralManager: CBCentralManager?
let nodle = Nodle.sharedInstance
override func viewDidLoad() {
    super.viewDidLoad()
    // Do any additional setup after loading the view.

    // set manager for permissions
    locationManager.delegate = self

    // check status for location permission
    switch CLLocationManager.authorizationStatus() {
    case .authorizedWhenInUse, .authorizedAlways:
        // request always auth if you would use it in the background otherwise requestWhileInUse
        locationManager.requestAlwaysAuthorization()
        // ask for bluetooth permissions
        centralManager = CBCentralManager(delegate: self, queue: nil)
    case .notDetermined:
        // request always auth if you would use it in the background otherwise requestWhileInUse
        locationManager.requestAlwaysAuthorization()
    default:
        print("Location permission denied")
        break;
    }
}

func startNodle() {
    // start the sdk
    nodle.start(devKey: "ss58:5FUfDdHhtn5Bzgte69zr1NyNRS7zFqy7CnjVcRUUpWpXz3Cv", tags: "","")
}

func stopNodle() {
    // stop the sdk
    nodle.stop()
}

func centralManagerDidUpdateState(_ central: CBCentralManager) {
    switch central.state {
    case .poweredOn:
        // start Nodle after Bluetooth permissions have been granted
        startNodle()
        break
    case .poweredOff:
        // stop nodle
        stopNodle()
        break
    default:
        break
    }
}

func locationManager(_ manager: CLLocationManager, didChangeAuthorization status: CLAuthorizationStatus) {
    // handle success
    if status == .authorizedWhenInUse || status == .authorizedAlways {
        print("Location permission have been granted")
        // ask for ble permissions
        centralManager = CBCentralManager(delegate: self, queue: nil)
    }
}
}
import UIKit
import SwiftCBOR
import SwiftProtobuf
import NodleSDK
import SQLite
import CoreLocation
class ViewController: UIViewController, CLLocationManagerDelegate {
private let locationManager = CLLocationManager()
let nodle = Nodle.sharedInstance
override func viewDidLoad() {
    super.viewDidLoad()
    // Do any additional setup after loading the view.

    // set manager for permissions
    locationManager.delegate = self

    // check status for location permission
    switch CLLocationManager.authorizationStatus() {
    case .authorizedWhenInUse, .authorizedAlways:
        // request always auth if you would use it in the background otherwise requestWhileInUse
        locationManager.requestAlwaysAuthorization()
    case .notDetermined:
        // request always auth if you would use it in the background otherwise requestWhileInUse
        locationManager.requestAlwaysAuthorization()
    default:
        print("Location permission denied")
        break;
    }
}

func startNodle() {
    // start the sdk
    nodle.start(devKey: "ss58:5FUfDdHhtn5Bzgte69zr1NyNRS7zFqy7CnjVcRUUpWpXz3Cv", tags: "","")
}

func stopNodle() {
    // stop the sdk
    nodle.stop()
}

func locationManager(_ manager: CLLocationManager, didChangeAuthorization status: CLAuthorizationStatus) {
    // handle success
    if status == .authorizedWhenInUse || status == .authorizedAlways {
        print("Location permission have been granted")
        // start Nodle after Location permissions have been granted
        startNodle()
    } else {
        // stop nodle if permissions revoked
        stopNodle()
    }
}
}
// MARK: 1. Choose the permissions you need:
let permissions: [SPPermissions.Permission] = [.location, .bluetooth]
// MARK: 2. Choose present style:
// 2a. List Style
let controller = SPPermissions.list(permissions)
controller.present(on: self)
// 2b. Dialog Style
let controller = SPPermissions.dialog(permissions)
controller.present(on: self)
// 2c. Native Style
let controller = SPPermissions.native(permissions)
controller.present(on: self)
// MARK: 3. Optional: Check permission state (available `authorized`, `denied`, `notDetermined`):

let authorized = SPPermissions.Permission.calendar.authorized
nodle.getEvents { event in
// collect the NodleEvent events by chosing a type
switch event.type {
case .BlePayloadEvent:
let payload = event as! NodleBluetoothRecord
print("Bluetooth payload available \(payload.device)")
break
case .BleStartSearching:
print("Bluetooth started searching")
break
case .BleStopSearching:
print("Bluetooth stopped searching")
break
@unknown default:
print("Failed to get any event")
}
}
nodle.getEvents { event in
// collect the NodleEvent events by chosing a type
switch event.type {
case .BeaconPayloadEvent:
let payload = event as! NodleBeaconRecord
print("iBeacon payload available \(payload.identifier) major: \(payload.major) minor: \(payload.minor) delivered at \(Date())")
break
case .BeaconStartSeaching:
print("iBeacon started searching \(Date())")
break
case .BeaconStopSearching:
print("iBeacon stop searching \(Date())")
break
@unknown default:
print("Failed to get any event")
}
}
import UIKit
import SwiftCBOR
import SwiftProtobuf
import NodleSDK
import SQLite
import CoreLocation
import CoreBluetooth
// load the json config located in your app folder config.json
let bundle = Foundation.Bundle(identifier: "io.nodle.apptest.AppTest")

// path for the file in the project
let path = bundle!.path(forResource: "config", ofType: "json")

// or you can manually set the entries, for instance
Nodle().config("dtn.use-cellular", false);

// background mode selected - foreground only
Nodle().config("cron.ios-bg-mode", 0);

// then proceed to start Nodle
Nodle().start()