iOS

System requirements

With the Ramani API Framework for iOS, you can build apps that target native 32-bit or 64-bit devices running iOS 9.0 and later.

Developing an application with the Ramani API Framework for iOS requires the following:

  • Xcode 9.0 or later.
  • iOS SDK 11.0 or later (up to 11.0).
  • Google Maps SDK 3.0 or later.

Screen captures

RamaniMaps-screensho0t-01 RamaniMaps-Screenshoot-03 RamaniMaps-Screenshoot-06


Core functionality

  • Objective-C Library
  • Access online map data through various RAMANI Services
  • Support for Google Maps Services
  • Georeference information from the COPERNICUS and Sentinel data services
  • Store and Get geometry data in Ramani Cloud

Sample Project

To get All the samples source code, you can clone or download on this Project RamaniiOSTest


Getting started

These instructions will help you how to development with our Maps-API in your project. See descriptions below for our Maps-API.

Install And Import RamaniAPi POD Library

The Maps SDK for iOS is available as a CocoaPods pod. CocoaPods is an open source dependency manager for Swift and Objective-C Cocoa projects. If you don’t already have the CocoaPods tool, install it on macOS by running the following command from the terminal. For details, see the CocoaPods Getting Started guide. Here is the way how to install SDK into your project

  • Type sudo gem install cocoapods in terminal.
  • Create a file named Podfile in your project directory. This file defines your project’s dependencies. Or you can get podfile automatically by open a terminal and go to the directory containing the project :
cd <path-to-project>

then type pod init in terminal, the podfile will automatically available in your project file

  • Edit the Podfile and add your dependencies. Here is an example which includes the dependencies you need for the Maps SDK for iOS and Places SDK for iOS (optional):
source 'https://github.com/CocoaPods/Specs.git'
use_frameworks!
target 'RamaniiOSTest' do

pod 'GoogleMaps'
pod 'RamaniApi', :git => 'https://team.ujuizi.com:6443/RAMANI/iospods.git', :tag => '2.0.0'

end

post_install do |installer|
  installer.aggregate_targets.each do |aggregate_target|
    if aggregate_target.name == 'Pods-RamaniiOSTest'
      aggregate_target.xcconfigs.each do |config_name, config_file|
        aggregate_target.pod_targets.each do |pod_target|
          pod_target.specs.each do |spec|
            if spec.attributes_hash['vendored_frameworks'] != nil or (spec.attributes_hash['ios'] != nil and spec.attributes_hash['ios']['vendored_frameworks'] != nil)
              frameworkPaths = unless spec.attributes_hash['ios'].nil? then spec.attributes_hash['ios']['vendored_frameworks'] else spec.attributes_hash['vendored_frameworks'] end || Set.new
            frameworkNames = Array(frameworkPaths).map(&:to_s).map do |filename|
              extension = File.extname filename
              File.basename filename, extension
            end
            frameworkNames.each do |name|
              puts "Removing #{name} from OTHER_LDFLAGS"
              config_file.frameworks.delete(name)
            end
          end
        end
      end
      xcconfig_path = aggregate_target.xcconfig_path(config_name)
      config_file.save_as(xcconfig_path)
    end
  end
end
end
  • Don’t forget to change YOUR_PROJECT_NAME to your project name
  • Save the Podfile.
  • Run the pod install command. This will install the APIs specified in the Podfile, along with any dependencies they may have.
  • Before using RamaniApi code, don’t forget add import RamaniApi on your Swift code, or add #import <Ramani/RSMapServices.h> on your Objective-C code.

Import RamaniApi using Library File

Follow the step bellow to implement our library into your project :

  • Download and extract the newest framework library (RamaniAPI iOS 2.0.1)
  • Create new project or open your own project that you want to implement the framework library
  • Drag and drop the library that you’ve downloaded before inside your project, or you can do it in another way, you can go to :
    • build phase
    • link binary with libraries
    • click + button to add the framework library or click - button to remove the framework library
  • Create .h file inside your project, name it [your project name]-Bridging-Header.h
  • Import Framework library into [your project name]-Bridging-Header.h file
  • Make sure your Briding-Header file already registered on your Project Build Settings>Objective-C Bridging Header (see This Insctructions)
#ifndef [your\_project\_name]\_Bridging\_Header\_h
#define [your\_project\_name]\_Bridging\_Header\_h
#endif /\* [your\_project\_name]\_Bridging\_Header\_h \*/

#import <RamaniApi/RSMapServices.h>
#import <RamaniApi/RSSyncTileLayer.h>

API-Key

You must provide the API-Key that you get from our client-area webpage before accessing our services. Below is the step-by-step guide to create new API Key:

  • Sign in. Or Register first, if you don't have an account yet
  • Login to your dashboard.
  • Select tab Configuration and your API Key is there.

api-key


Add API Key on Your Code

After you get your API Key, add your API key to your AppDelegate.swift :

  • Add the following to your application(_:didFinishLaunchingWithOptions:) method, replacing YOUR_API_KEY with your API key, and YOUR_USERNAME with your username (see API KEY):
RSMapServices.apiKey("YOUR_API_KEY", userName: "YOUR_USERNAME", schema: "public")

Note:

  • public is the default Schema name.

Sample Codes

Get Ramani Public Layer ID

public-layerid

  1. Goto Ramani Public Maps
  2. Click on layer button.
  3. Select the datasets you want to use.
  4. Login if you are not loggin yet.
  5. Draw something on the map.
  6. Click get code button.
  7. You will see the Layer ID and also some code snippet.
  8. For sample public.username_SWTRR.

Get Private Layer ID

private-layerid-0 private-layerid-1

  1. Login to your Ramani Cloud Account
  2. Click Editor button from your dashboard.
  3. Select the Database tab.
  4. The Layer ID is combination of Schema and Table ID, here you schema name.
  5. This is your layer ID.
  6. For sample public.SWTRR.

Load Map Layer (using layerID)

With the Ramani API Framework for iOS, you can add a Map Layer to your application. The code below demonstrates how to add a map layer to an existing ViewController.

import RamaniApi //add this

class YourViewController {
    private var mapView_: GMSMapView?
    let layerId = "ddl.simS3seriesCoverGlobal.coverclass"

    override func loadView() {
        let camera = GMSCameraPosition.camera(withLatitude: 0, longitude: 0, zoom: 8)
        mapView = GMSMapView.map(withFrame: CGRect.zero, camera: camera)
        mapView?.isMyLocationEnabled = true

        // set this for Tap up Event on Map
        mapView?.delegate = self
        view = mapView

        ///create map tile layer
        let tileLayer :RSSyncTileLayer = RSMapServices.getMap("LayerID") as! RSSyncTileLayer
        tileLayer.map = mapView

    }

}

Load Map Layer (using Ramani Analytics URL)

If you are using Ramani Analytics URL, the usage is the same as layerID.
But sometimes, the url can be too long. Therefore, you can use the shorten URL by clicking Get Maps-API Endpoint on your OPeNDAP URL page, Data Files section. And then, copy the URL.

// Global Night time Lights sentinel 3 https://analytics.ramani.ujuizi.com/goto/d831a7cc7346e63ca861ec6748450d4d
            	
//Add opendap URL here and add .wms at the end of URL
let params = ["dataset": "https://analytics.ramani.ujuizi.com/goto/d831a7cc7346e63ca861ec6748450d4d

Get Location Info (getPoint)

To get more features information at a single point. Retrieves data, including geometry and attribute values.

let coordinate = CLLocationCoordinate2D(latitude: 47.18224592701491, longitude: 8.581695556640627);
let pointInfo = RSMapServices.getPoint(coordinate, layerID: "YOUR_LAYERID")
print("pointInfo : \(String(describing: pointInfo))")

<i>Note</i>: The getPoint operation is designed to provide clients with more information about a single location on a map.


Get Vertical Profile

To get more features information at a single point(Get Point), along a vertical dimension.

let coordinate = CLLocationCoordinate2D(latitude: 47.18224592701491, longitude: 8.581695556640627);
let getVerticleProfile = RSMapServices.getVerticleProfileJson(coordinate, layerID: "YOUR_LAYERID");
print("getVerticleProfile : (String(describing: getVerticleProfile))");

Note:

  • Only works on layers that have a temporal dimension (explore the maps we have offer in our DDL), for example nitrates in the depth of the ocean
  • Only support for JSON, PNG, and SVG.
  • To get layer capabilities (attribute) or if you want to set custom parameter.

Get Time-series Profile

To get more features information at a single point(Get Point), along with variation in time (along a temporal dimension).

let coordinate = CLLocationCoordinate2D(latitude: 47.18224592701491, longitude: 8.581695556640627);
var params = ["TIME": "2010-02-04T00:00:00.000Z/2010-04-15T00:00:00.000Z"]
RSMapServices.params = params
let getTimeSeriesProfile = RSMapServices.getTimeseriesProfileJson(coordinate, layerID: "YOUR_LAYERID");
print("getTimeSeriesProfile : (String(describing: getTimeSeriesProfile))");

Note:

  • Only works on layers that have a temporal dimension (explore the maps we have offer in our DDL), for example Leaf Area Index (LAI) over the seasons of the year
  • Only support for JSON, PNG, and SVG.
  • To get layer capabilities (attribute) or if you want to set custom parameter.

Get Horizontal Profile (GetTransect)

To get more features information at multiple point, along a horizontal dimension. For example, atmospheric ozone along a line (single or multiple segments) crossing a city.

private var arrayCoordinates = NSMutableArray(array:
  [
    CLLocation(latitude: 8.134002685546877 , longitude: 47.23542209101768),     
    CLLocation(latitude: 8.489685058593752 , longitude: 47.32579231609051),     
  ])
let getTransect = RSMapServices.getTransectJson(arrayCoordinates, layerID: "YOUR_LAYERID");
print("getTransect : (String(describing: getTransect))");

Note:


Get Area Profile

To get more features information at multiple point, along a horizontal dimension. But for an area defined by PolygonOptions.

private var arrayCoordinates = NSMutableArray(array:
    [
        CLLocation(latitude: 8.661346435546877 , longitude: 47.28295557691233),     
        CLLocation(latitude: 8.661346435546877 , longitude: 47.32951560950959),     
        CLLocation(latitude: 8.672332763671797 , longitude: 47.28295557691233),     
        CLLocation(latitude: 8.720397949218793 , longitude: 47.33603074146188),     
        CLLocation(latitude: 8.740997314453045 , longitude: 47.28295557691233),     
        CLLocation(latitude: 8.760223388671877 , longitude: 47.3164829342833),     
        CLLocation(latitude: 8.760223388671877 , longitude: 47.3164829342833),     
    ])
let areaJSON = RSMapServices.getAreaJson(arrayCoordinates, layerID: "YOUR_LAYERID",  returnType: "aggregate")
print("areaJSON : (String(describing: areaJSON))");

Note:

  • Only support for JSON, PNG, SVG.
  • Only support for dataType : ALL, HISTOGRAM, and AGGREGATE.
  • Explore the maps we have offer in our DDL.
  • To get layer capabilities (attribute) or if you want to set custom parameter.

Return Example :

{
  "type": "GetAreaResponse",

  "area": {
      "crs": "EPSG:4326",
      "linestring": "3.53759765625 47.79839667295524,4.556673569110679 48.07338898931344,3.4914556008582487 47.49998727341379,5.2789456005429924 47.913809258555474,3.3776305571161824 46.756562106822706,5.6348949137565185 47.21247952521911,3.787219268892672 46.519273910457045,4.775344730497775 46.848707252177114,4.775344730497775 46.848707252177114,",
      "dataset": "Sentinel-3: Global Nighttime Lights",
      "variable": "Nighttime Lights",

      "units": "",
      "aggregate": {
          "mean": 6.622666666666683,
          "stdv": 8.875178801281983,
          "skew": 2.6443954084095673,
          "kurt": 9.388449667730299,

          "min": 0,
          "max": 61,
          "perc": 6,

          "median": 6
      },
      "histogram": [
          "{frequency=2.0, value=54.0}",
          "{frequency=1.0, value=56.0}",
          ...
          "{frequency=2.0, value=16.0}",
          "{frequency=1.0, value=15.0}",

          "{frequency=2.0, value=18.0}"
      ]

      }
  }

Get Point Cube

The extended version of Get Feature Info (Get Point). Where you’re able to not just get the information on a single point, but also the information of the neighboor GeoPoint, in a 3x3, 5x5, etc bounding box. It would be usefull for a comparison (e.g temperature between all neighboring pixels in a 3x3).

In order to create a grid(rectangular), a bounding box is needed. And every bounding box has a radius, which is the distance from your center point to the outer edge of bounding box. And the diameter, which is the distance between outer edge, or always twice the radius.

The radius value in our API is the latlong distance(e.g. distance from GeoPoint(10.00, 10.00) to GeoPoint(10.00, 10.50) will has 0.5 distance in lon (± 50Km)). And if you set your radius at 0.5, your diameter(grid width) will be 1. This also means, the distance between bounding box center point in your grid, is 1 (diameter).

let coordinate = CLLocationCoordinate2D(latitude: 47.18224592701491, longitude: 8.581695556640627);
let radius = Int32(1)
let gridSize = Int32(3) // supports >=3
let pointCube = RSMapServices.getPointCubeJson(coordinate, layerID: "YOUR_LAYERID", grid: gridSize , radius: radius)
print("pointCube : (String(describing: pointCube))");

The code above will give you 9 data points, since you're requesting for 3x3 grid size. The value itself once again, depend on your GeoPoint and Radius.

 You  tapped  at  8.581695556640627,  47.18224592701491
featureInfo  JSON  : {
  "success" : 1,
  "data" : [
    {
      "type" : "FeatureInfoResponse",
      "features" : [
        {
          "geometry" : "8.581695556640627 47.18224592701491",
          "properties" : {
            "gridCentreLon" : 8.581695556640627,
            "jIndex" : 45426,
            "iIndex" : 117396,
            "gridCentreLat" : 47.18224592701491
          },
          "featureInfo" : [
            {
              "value" : 14,
              "time" : "2009-01-01T00:00:00.000Z"
            }
          ]
        }
      ]
    },
    ....
  ]
}

With the order from the Bottom Left (the lowest coordinate) to Top Right (the higher coordinate). Below is the visualization of the 3x3 grid indices, where the (0,0) is your original GeoPoint:

Point Cube

Note:

  • Only support for grid size with odd value and >= 3
  • Explore the maps we have offer in our DDL

Get Layer Attributes(GetMetadata)

To requests metadata (e.g. date-range, layer details, units, etc.) from layer dataset. For example, to obtain the temporal range of a time-series required by getTimeseriesProfile use (TIME), or to get the extremes of a layer (Min), and (Max) to set the scaleRange parameter.

var getMetadata = RSMapServices.getMetadata(layerId)

Note:

  • Only support JSON.
  • For more information about which parameters you can get follow this link.
  • Explore the maps we have offer in our DDL.

Get dates for timeseries and return as RSS

Using Get Layer Attributes method, below is the example to get (TIME) for Get Time-series Profile:

var params = ["item": "dates", "format": "rss"]
RSMapServices.params = params

var getMetadata = RSMapServices.getMetadata(layerID)

Get dates for timeseries and return ISO8601 format

Using Get Layer Attributes method, below is the example to get (TIME) for Get Time-series Profile:

var params = ["item": "dates"]
RSMapServices.params = params

var getMetadata = RSMapServices.getMetadata(layerID)

Note:

  • Only support JSON.
  • For more information about which parameters you can get follow this link.
  • Explore the maps we have offer in our DDL.

Set Layer Attributes (setParams)

Set Parameter is used to add or replace existing parameters, to make your requested data richer and more dynamic. Make sure to call setParams(params) before executing your request, or the API will use your default parameter.

var params = ["TIME": "2010-02-04T00:00:00.000Z/2010-04-15T00:00:00.000Z"]
RSMapServices.params = params
var img: UIImage? = RSMapServices.getTimeseriesProfile(coordinate, layerID: layerID)
var myImageView = UIImageView(image: img)
view.addSubview(myImageView)
  • The example above use param (TIME) to set the temporal range of a time-series.
  • For more information about which parameters you can set, follow this link.
  • Explore the maps we have offer in our DDL.

Manipulate Your Data in Our Cloud

With this method, you can do CRUD (Create, Read, Update, Delete) to your dataset. The first example shows how to search for a feature in a layer and show it on the map, the second shows how to insert a new point (i.e. GPS-location).

var yourdata = RSMapServices.sqlAPI("SELECT * FROM [schemaName].[layerID] WHERE round(ST_Distance(ST_Transform(\"the_geom\",3857),
            'ST_GeomFromText('POINT(551569.5961058318 6701998.640044251)',3857))) < 6114.9622628
            ORDER BY round(ST_Distance(ST_Transform(\"the_geom\",3857),
            ST_GeomFromText('POINT(551569.5961058318 6701998.640044251)',3857)))LIMIT 5");
print(yourdata)
  • Basically, you're using PostgreSQL query syntax
  • Only work for dataset/layer under your account(private)
  • Explore the maps we have offer in our DDL.

Store Geometry Data

Store your single point or multiple point such as linestring, polygon on our Cloud Service as Geometry data.

let coordinate = CLLocationCoordinate2D(latitude: 47.18224592701491, longitude: 8.581695556640627);
var fields = ["id": "100", "time": "1434159945524", "accelx": "4.338"]
RSMapServices.storePoint(layerID, fields: fields, coordinate: coordinate)

var fields = ["id": "100", "time": "1434159945524", "accelx": "4.338"]
RSMapServices.storeLine(coordinates, layerID: layerID, fields: fields)

var fields = ["id": "100", "time": "1434159945524", "accelx": "4.338"]
RSMapServices.storePolygon(coordinates, layerID: layerID, fields: fields)
  • Only work for dataset/layer under your account(private)
  • If you do not have any dataset in your account, in your account go to Editor >> Database

<!--

See Also


-->

License

Copyright (c) 2017 RAMANI B.V.

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.