Skip to content

Custom Places

It is possible to add custom Points of Interest (POIs). We call them Places. Places can be used for example to show the user's favorite places or places that are not available in the Sygic database. To be able to show custom places on the map, it is necessary to inject a skin definition for them.

In the next chapters, we will see how to import custom places from a JSON file, how to install them from the server or how to use them without downloading them.

Enabling Custom Places and modes

To enable custom places at startup, it is necessary to set Custom Places as the startupPoiProvider in the JSON Config:

"MapReaderSettings": {
    "startup_poi_provider": "CustomPlaces",
}

By setting the Custom Places POI provider at startup, both map places and custom places will be visible in the map.

Setting the mode

There are two modes in which custom places can be used:

  • Offline
  • Online

Online mode means that the places are downloaded from the server while browsing the map or along the calculated route. This mode is suitable for places that are frequently updated. This is automatically managed by the SDK.

Offline mode means that the places are downloaded using the methods described below and stored in the app's database. They are not continually downloaded from the server.

Important

Before using the online or offline mode, it is necessary to set it like this: SYCustomPlacesManager.shared()?.mode = .offline

Tip

Depending on your preferences, it might be a good idea to download the offline places upon downloading a map as the places are tied to iso codes (and you get them via SYMapInstaller). Then, you can update them according to your needs.

Injecting a skin for Custom Places

To be able to see custom places on the map, you need to inject a skin definition for them. The skin definition is defined by a JSON that contains the style of the custom places, basically for groups and categories. Below is a sample of importing the skin definition:

Important

If not defined in the skin_default.xml file, it will be necessary to inject the skin at each mapView creation.

let skinDefinitionToInject = """
    {
      "skin": {
        "poi_categories": {
          "custom": {
            "groups": {

              "SYPotato": {
                "enabled": true,
                "color": "0xb38c00ff",
                "icon": "0xe335",
                "priority": 24,
                "showWithoutText": true,
                "zoomLevel": 17.9
              }
            },
            "categories": {
              "new_custom_category": {
                "groupId": "SYPotato"
              },
              "anotherCategory": {
                "groupId": "SYPotato"
              }
            }
          }
        }
      }
    }
    """

mapView.injectSkinDefinition( skinDefinitionToInject ) { result in
    print("skin injected with result: \(result)")
}

Importing Custom Places from a JSON file

After having a JSON file with custom places ready, it is possible to import it using the following code:

SYCustomPlacesManager.shared()?.installOfflinePlaces(fromJson: "as_a_string") { error in
    // do something
}

If you do not define a "dataset", the places wil be imported into the default dataset. The ID of the default dataset is "bf19e514-487b-43c4-b0df-9073b2397dd1".

Deleting Custom Places using a JSON file

It is also possible to delete custom places using a JSON file. For example, if you want to remove the custom place from custom places article, your JSON file would look like this:

{
  "to_remove": [
    "3047426d-849b-de0b-e82a-24c699c0b9a4"
  ]
}

Then, just call the same method as above to install the places. The place will be removed from the database. Removing is specified by the "to_remove" key in the JSON file. You can add/update and remove places in the same JSON file.

Installing custom places from server

After having the custom places uploaded to the server, it is possible to install them in your app. For further information about uploading the places to the server, please see the Custom Places API and the the Custom Places article

Installing

To install custom places from the server, you need to call the following method:

SYCustomPlacesManager.shared()?.installOfflinePlaces(fromDatasets: ["dataset_name"], forCountry: "iso", progress: { progress in
    print("progress: " + String(progress.loadedRecords) + "/" + String(progress.totalRecords))
}, completion: { error in
    print("finished " + error.debugDescription)
})

The method above installs places of the specified dataset for the specified country iso. Alternatively, you can install all datasets of a specific country:

SYCustomPlacesManager.shared()?.installOfflinePlaces(fromDatasets: [], forCountry: "iso", progress: { progress in
    print("progress: " + String(progress.loadedRecords) + "/" + String(progress.totalRecords))
}, completion: { error in
    print("finished " + error.debugDescription)
})

Or, you can install one dataset for all countries:

SYCustomPlacesManager.shared()?.installOfflinePlaces(fromDatasets: ["dataset_name"], forCountry: nil, progress: { progress in
    print("progress: " + String(progress.loadedRecords) + "/" + String(progress.totalRecords))
}, completion: { error in
    print("finished " + error.debugDescription)
})

Uninstalling

To uninstall custom places from the server, you need to call one of the following methods:

// this one uninstalls the specific dataset of the specific country
SYCustomPlacesManager.shared()?.uninstallOfflinePlaces(fromDatasets: ["dataset_name"], forCountry: "iso", completion: { error in
    print("uninstalled with status: " + error.debugDescription )
})

// and using this method, you can uninstall all datasets of the specific country
SYCustomPlacesManager.shared()?.uninstallOfflinePlaces(forCountry: "iso", completion: { error in
    print("uninstalled with status: " + error.debugDescription )
})

Updating

To update custom places from the server, you need to call the following method:

Note

Please note that this method updates all of the installed places, not just the ones from the specified country.

SYCustomPlacesManager.shared()?.updateInstalledPlaces(progress: { progress in
    print("progress: " + String(progress.loadedRecords) + "/" + String(progress.totalRecords))
}, completion: { error in
    print("finished " + error.debugDescription)
})

You can read more about the Custom Places Search in the Custom Places Search article.

EV Custom Places

This page documents the new EV functionality introduced in SDK29 for iOS. It includes detailed electric vehicle charging information available through SYPlace, new data models, filtering capabilities, and best practices for integration.

EV Extensions in SYPlace

The SYPlace model has been extended with support for detailed EV charging station data:

evCharger: SYPlaceEVCharger*
vehicleRestrictions: SYPlaceVehicleRestrictions*
paymentMethods: NSSet<NSNumber*>*
serviceProviders: NSArray<NSString*>*

These types provide structured access to charging equipment, supported connector types, voltage and power ranges, supported payment methods, and vehicle access restrictions.

EV Charger

@interface SYPlaceEVCharger : NSObject
@property(nonatomic, strong, nullable) NSNumber* isPublic;
@property(nonatomic, strong, nullable) NSNumber* isFreeOfCharge;
@property(nonatomic, strong, nullable) NSString* operatorName;
@property(nonatomic, strong, nullable) NSString* externalId;
@property(nonatomic, strong, nullable) NSArray<SYPlaceEVEquipment*>* equipment;
@end

EV Equipment and Connectors

@interface SYPlaceEVEquipment : NSObject
@property(nonatomic, strong, nullable) NSSet<NSNumber*>* authorizationTypes;
@property(nonatomic, strong, nullable) NSArray<SYPlaceEVConnector*>* connectors;
@end

@interface SYPlaceEVConnector : NSObject
@property(nonatomic, strong, nullable) NSString* externalId;
@property(nonatomic, assign) SYEVConnectorType type;
@property(nonatomic, strong, nullable) NSNumber* voltage;
@property(nonatomic, assign) float maxPower;
@property(nonatomic, assign) SYEVPowerType powerType;
@property(nonatomic, assign) SYEVConnectorFormat format;
@end

Connector Enums

typedef NS_ENUM(NSInteger, SYEVConnectorType) { ... };
typedef NS_ENUM(NSInteger, SYEVPowerType) { ... };
typedef NS_ENUM(NSInteger, SYEVConnectorFormat) { ... };
typedef NS_ENUM(NSInteger, SYEVChargerAuthorizationType) { ... };
typedef NS_ENUM(NSInteger, SYPaymentMethod) { ... };

Filtering EV Stations

When displaying or filtering EV stations, use the extended properties to apply business logic, such as:

Filtering by connector type

place.evCharger?.equipment?.flatMap { $0.connectors }.filter { $0.type == .ccs2_socket }

Filtering by payment method

place.paymentMethods?.contains(NSNumber(value: SYPaymentMethodCreditCard.rawValue))

Filtering by authorization

place.evCharger?.equipment?.flatMap { $0.authorizationTypes }.contains(NSNumber(value: SYEVChargerAuthorizationTypeRFID.rawValue))

Filtering by Service Provider

place.serviceProviders.contains("sk.emsp.greenway")

Migration Notes

The following APIs have been deprecated or removed in SDK29

• SYPlaceLink usage replaced by SYPlace* references • Methods from SYPlacesManager like: loadEVConnector, addIndividualPlaces, loadExternalPlaceId, … • SYPlaceDetailAttributes entries like SYMaxPower, SYConnectorType, … were removed

Instead, use the strongly typed properties now available in SYPlace, SYPlaceEVCharger, etc.

Integration Recommendations

• When no EV data is available, evCharger will be nil

Example Access

if let evCharger = place.evCharger {
    for equipment in evCharger.equipment ?? [] {
        for connector in equipment.connectors ?? [] {
            print("Connector type: \(connector.type), maxPower: \(connector.maxPower)")
        }
    }
}