Delen via


Een gegevensbron maken in de iOS SDK (preview)

Notitie

Buitengebruikstelling van Azure Kaarten iOS SDK

De Azure Kaarten Native SDK voor iOS is nu afgeschaft en wordt buiten gebruik gesteld op 3-31-25. Om serviceonderbrekingen te voorkomen, migreert u tegen 3-31-25 naar de Azure Kaarten Web SDK. Zie de migratiehandleiding voor de Azure Kaarten iOS SDK voor meer informatie.

De Azure Kaarten iOS SDK slaat gegevens op in gegevensbronnen. Het gebruik van gegevensbronnen optimaliseert de gegevensbewerkingen voor het uitvoeren van query's en rendering. Er zijn momenteel twee typen gegevensbronnen:

  • GeoJSON-bron: beheert onbewerkte locatiegegevens in geoJSON-indeling lokaal. Geschikt voor kleine tot middelgrote gegevenssets (omhoog van honderdduizenden shapes).
  • Vectortegelbron: laadt gegevens die zijn opgemaakt als vectortegels voor de huidige kaartweergave, op basis van het tegelsysteem voor kaarten. Ideaal voor grote tot enorme gegevenssets (miljoenen of miljarden shapes).

GeoJSON-gegevensbron

Azure Kaarten gebruikt GeoJSON als een van de primaire gegevensmodellen. GeoJSON is een open georuimtelijke standaardmethode voor het weergeven van georuimtelijke gegevens in JSON-indeling. GeoJSON-klassen die beschikbaar zijn in de Azure Kaarten iOS SDK om GeoJSON-gegevens eenvoudig te maken en te serialiseren. Laad en sla GeoJSON-gegevens in de DataSource klasse op en geef deze weer met behulp van lagen. De volgende code laat zien hoe GeoJSON-objecten kunnen worden gemaakt in Azure Kaarten.

/*
    Raw GeoJSON feature

    {
        type": "Feature",
        "geometry": {
            "type": "Point",
            "coordinates": [-100, 45]
        },
        "properties": {
            "custom-property": "value"
        }
    }

*/

//Create a point feature.
let feature = Feature(Point(CLLocationCoordinate2D(latitude: 45, longitude: -100)))

//Add a property to the feature.
feature.addProperty("custom-property", value: "value")

//Add the feature to the data source.
source.add(feature: feature)

De eigenschappen kunnen ook eerst in een woordenlijst (JSON) worden geladen en vervolgens worden doorgegeven aan de functie bij het maken, zoals in de volgende code wordt gedemonstreerd:

//Create a dictionary to store properties for the feature.
var properties: [String: Any] = [:]
properties["custom-property"] = "value"

let feature = Feature(Point(CLLocationCoordinate2D(latitude: 45, longitude: -100)), properties: properties)

Zodra u een GeoJSON-functie hebt gemaakt, kan er via de sources eigenschap van de kaart een gegevensbron aan de kaart worden toegevoegd. De volgende code laat zien hoe u een functie DataSourcemaakt, toevoegt aan de kaart en een functie toevoegt aan de gegevensbron.

//Create a data source and add it to the map.
let source = DataSource()
map.sources.add(source)

//Add GeoJSON feature to the data source.
source.add(feature: feature)

De volgende code toont verschillende manieren om een GeoJSON Feature- FeatureCollectionen geometrieën te maken.

// GeoJSON Point Geometry
let point = Point(location)

// GeoJSON LineString Geometry
let polyline = Polyline(locations)

// GeoJSON Polygon Geometry
let polygon = Polygon(locations)

let polygonWithInteriorPolygons = Polygon(locations, interiorPolygons: polygons)

// GeoJSON MultiPoint Geometry
let pointCollection = PointCollection(locations)

// GeoJSON MultiLineString Geometry
let multiPolyline = MultiPolyline(polylines)

let multiPolylineFromLocations = MultiPolyline(locations: arrayOfLocationArrays) // [[CLLocationCoordinate2D]]

// GeoJSON MultiPolygon Geometry
let multiPolygon = MultiPolygon(polygons)

let multiPolygonFromLocations = MultiPolygon(locations: arrayOfLocationArrays) // [[CLLocationCoordinate2D]]

// GeoJSON GeometryCollection Geometry

let geometryCollection = GeometryCollection(geometries)

// GeoJSON Feature
let pointFeature = Feature(Point(location))

// GeoJSON FeatureCollection
let featureCollection = FeatureCollection(features)

GeoJSON serialiseren en deserialiseren

De functiesverzameling, functie en geometrieklassen hebben fromJson(_:) allemaal en toJson() statische methoden, die helpen bij serialisatie. De opgemaakte geldige JSON-tekenreeks die via de fromJson() methode wordt doorgegeven, maakt het geometrieobject. Deze fromJson() methode betekent ook dat u kunt gebruiken JSONSerialization of andere serialisatie-/deserialisatiestrategieën. De volgende code laat zien hoe u een tekenreeksgewijze GeoJSON-functie kunt gebruiken en deze in de Feature klasse deserialiseert en deze vervolgens weer in een GeoJSON-tekenreeks serialiseert.

// Take a stringified GeoJSON object.
let geoJSONString = """
    {
        "type": "Feature",
        "geometry": {
            "type": "Point",
            "coordinates": [-100, 45]
        },
        "properties": {
            "custom-property": "value"
        }
    }
"""

// Deserialize the JSON string into a feature.
guard let feature = Feature.fromJson(geoJSONString) else {
    throw GeoJSONSerializationError.couldNotSerialize
}

// Serialize a feature collection to a string.
let featureString = feature.toJson()

GeoJSON-gegevens importeren vanaf internet of uit een map met assets

De meeste GeoJSON-bestanden bevatten een FeatureCollection. Lees GeoJSON-bestanden als tekenreeksen en gebruik de FeatureCollection.fromJson(_:) methode om deze te deserialiseren.

De DataSource klasse heeft een ingebouwde methode importData(fromURL:) die geoJSON-bestanden kan laden met behulp van een URL naar een bestand op het web of het apparaat.

// Create a data source.
let source = DataSource()

// Import the geojson data and add it to the data source.
let url = URL(string: "URL_or_FilePath_to_GeoJSON_data")!
source.importData(fromURL: url)

// Examples:
// source.importData(fromURL: URL(string: "asset://sample_file.json")!)
// source.importData(fromURL: URL(string: "https://example.com/sample_file.json")!)

// Add data source to the map.
map.sources.add(source)

De importData(fromURL:) methode biedt een manier om een GeoJSON-feed in een gegevensbron te laden, maar biedt beperkte controle over hoe de gegevens worden geladen en wat er gebeurt nadat deze zijn geladen. De volgende code is een herbruikbare klasse voor het importeren van gegevens uit de map web of assets en het retourneren ervan naar de UI-thread via een callback-functie. In de callback kunt u vervolgens meer logica voor postbelasting toevoegen om de gegevens te verwerken, deze toe te voegen aan de kaart, het begrenzingsvak te berekenen en de camera van de kaarten bij te werken.

import Foundation

@objc
public class Utils: NSObject {
    /// Imports data from a web url or local file url and returns it as a string to a callback on the main thread.
    /// - Parameters:
    ///     - url: A web url or local file url that points to data to load.
    ///     - completion: The callback function to return the data to.
    @objc
    public static func importData(fromURL url: URL, completion: @escaping (String?) -> Void) {
        URLSession.shared.dataTask(with: url) { data, _, _ in
            DispatchQueue.main.async {
                if let data = data {
                    completion(String(decoding: data, as: UTF8.self))
                } else {
                    completion(nil)
                }
            }
        }.resume()
    }
}

De volgende code laat zien hoe u dit hulpprogramma gebruikt om GeoJSON-gegevens als een tekenreeks te importeren en deze via een callback terug te sturen naar de hoofdthread. In de callback kunnen de tekenreeksgegevens worden geserialiseerd in een GeoJSON-functieverzameling en worden toegevoegd aan de gegevensbron. Werk desgewenst de camera van de kaart bij zodat deze zich op de gegevens richt.

// Create a data source and add it to the map.
let source = DataSource()
map.sources.add(source)

// Create a web url or a local file url
let url = URL(string: "URL_to_GeoJSON_data")!
// Examples:
// let url = Bundle.main.url(forResource: "FeatureCollectionSample", withExtension: "geojson")!
// let url = URL(string: "www.yourdomain.com/path_to_feature_collection_sample")!

// Import the geojson data and add it to the data source.
Utils.importData(fromURL: url) { result in
    guard let result = result else {
        // No data imported.
        return
    }

    // Parse the data as a GeoJSON Feature Collection.
    guard let fc = FeatureCollection.fromJson(result) else {
        // Invalid data for FeatureCollection type.
        return
    }

    // Add the feature collection to the data source.
    source.add(featureCollection: fc)

    // Optionally, update the maps camera to focus in on the data.

    // Calculate the bounding box of all the data in the Feature Collection.
    guard let bbox = BoundingBox.fromData(fc) else {
        // The feature collection is empty.
        return
    }

    // Update the maps camera so it is focused on the data.
    map.setCameraBoundsOptions([
        .bounds(bbox),
        .padding(20)
    ])
}

Een functie bijwerken

De DataSource klasse maakt het eenvoudig om functies toe te voegen en te verwijderen. Voor het bijwerken van de geometrie of eigenschappen van een functie moet de functie in de gegevensbron worden vervangen. Er zijn twee methoden die kunnen worden gebruikt om een of meer functies bij te werken:

  1. Maak de nieuwe functies door de gewenste updates en vervang alle functies in de gegevensbron met behulp van de set methode. Deze methode werkt goed wanneer u alle functies in een gegevensbron wilt bijwerken.
var source: DataSource!

private func onReady(map: AzureMap) {
    // Create a data source and add it to the map.
    source = DataSource()
    map.sources.add(source)

    // Create a feature and add it to the data source.
    let myFeature = Feature(Point(CLLocationCoordinate2D(latitude: 0, longitude: 0)))
    myFeature.addProperty("Name", value: "Original value")
    source.add(feature: myFeature)
}

private func updateFeature() {
    // Create a new replacement feature with an updated geometry and property value.
    let myNewFeature = Feature(Point(CLLocationCoordinate2D(latitude: -10, longitude: 10)))
    myNewFeature.addProperty("Name", value: "New value")

    // Replace all features to the data source with the new one.
    source.set(feature: myNewFeature)
}
  1. Houd het functie-exemplaar in een variabele bij en geef deze door aan de methode voor gegevensbronnen remove om deze te verwijderen. Maak de nieuwe functie(s) met de gewenste updates, werk de verwijzing naar de variabele bij en voeg deze toe aan de gegevensbron met behulp van de add methode.
var source: DataSource!
var myFeature: Feature!

private func onReady(map: AzureMap) {
    // Create a data source and add it to the map.
    source = DataSource()
    map.sources.add(source)

    // Create a feature and add it to the data source.
    myFeature = Feature(Point(CLLocationCoordinate2D(latitude: 0, longitude: 0)))
    myFeature.addProperty("Name", value: "Original value")
    source.add(feature: myFeature)
}

private func updateFeature() {
    // Remove the feature instance from the data source.
    source.remove(feature: myFeature)

    // Get properties from original feature.
    var props = myFeature.properties

    // Update a property.
    props["Name"] = "New value"

    // Create a new replacement feature with an updated geometry.
    myFeature = Feature(
        Point(CLLocationCoordinate2D(latitude: -10, longitude: 10)),
        properties: props
    )

    // Re-add the feature to the data source.
    source.add(feature: myFeature)
}

Tip

Als u een aantal gegevens hebt die regelmatig worden bijgewerkt en andere gegevens die zelden worden gewijzigd, kunt u deze het beste splitsen in afzonderlijke gegevensbronexemplaren. Wanneer een update plaatsvindt in een gegevensbron, dwingt het de kaart om alle functies in de gegevensbron opnieuw te laden. Door deze gegevens op te splitsen, worden alleen de functies die regelmatig worden bijgewerkt, opnieuw geschilderd wanneer er een update plaatsvindt in die ene gegevensbron, terwijl de functies in de andere gegevensbron niet opnieuw hoeven te worden geschilderd. Dit helpt bij prestaties.

Vectortegelbron

Een vectortegelbron beschrijft hoe u toegang krijgen tot een vectortegellaag. Gebruik de VectorTileSource klasse om een vectortegelbron te instantiëren. Vectortegellagen zijn vergelijkbaar met tegellagen, maar ze zijn niet hetzelfde. Een tegellaag is een rasterafbeelding. Vectortegellagen zijn een gecomprimeerd bestand in PBF-indeling . Dit gecomprimeerde bestand bevat vectorkaartgegevens en een of meer lagen. Het bestand kan worden weergegeven en gestijld op de client, op basis van de stijl van elke laag. De gegevens in een vectortegel bevatten geografische kenmerken in de vorm van punten, lijnen en veelhoeken. Er zijn verschillende voordelen van het gebruik van vectortegellagen in plaats van rastertegellagen:

  • Een bestandsgrootte van een vectortegel is doorgaans veel kleiner dan een equivalente rastertegel. Als zodanig wordt minder bandbreedte gebruikt. Dit betekent een lagere latentie, een snellere kaart en een betere gebruikerservaring.
  • Omdat vectortegels op de client worden weergegeven, passen ze zich aan de resolutie van het apparaat waarop ze worden weergegeven. Als gevolg hiervan worden de gerenderde kaarten beter gedefinieerd, met kristalheldere labels.
  • Als u de stijl van de gegevens in de vectorkaarten wijzigt, hoeft u de gegevens niet opnieuw te downloaden, omdat de nieuwe stijl op de client kan worden toegepast. Als u daarentegen de stijl van een rastertegellaag wijzigt, moet u meestal tegels van de server laden en vervolgens de nieuwe stijl toepassen.
  • Omdat de gegevens in vectorvorm worden geleverd, is er minder verwerking aan de serverzijde vereist om de gegevens voor te bereiden. Hierdoor kunnen de nieuwere gegevens sneller beschikbaar worden gesteld.

Azure Kaarten voldoet aan de Mapbox Vector Tile Specification, een open standaard. Azure Kaarten biedt de volgende vectortegels als onderdeel van het platform:

Tip

Wanneer u vector- of rasterafbeeldingtegels uit de Azure Kaarten render-service gebruikt met de iOS SDK, kunt u vervangen door atlas.microsoft.com de AzureMapeigenschap domainPlaceholder's. Deze tijdelijke aanduiding wordt vervangen door hetzelfde domein dat door de kaart wordt gebruikt en voegt automatisch dezelfde verificatiegegevens toe. Dit vereenvoudigt de verificatie met de renderservice aanzienlijk bij het gebruik van Microsoft Entra-verificatie.

Als u gegevens van een vectortegelbron op de kaart wilt weergeven, verbindt u de bron met een van de gegevensweergavelagen. Alle lagen die een vectorbron gebruiken, moeten een sourceLayer waarde in de opties opgeven. Met de volgende code wordt de Tegelservice voor verkeersstromen in Azure Kaarten geladen als vectortegelbron en wordt deze vervolgens weergegeven op een kaart met behulp van een lijnlaag. Deze vectortegelbron heeft één set gegevens in de bronlaag met de naam 'Verkeersstroom'. De regelgegevens in deze gegevensset hebben een eigenschap traffic_level die in deze code wordt gebruikt om de kleur te selecteren en de grootte van regels te schalen.

// Formatted URL to the traffic flow vector tiles.
let trafficFlowUrl = "\(map.domainPlaceholder)/traffic/flow/tile/pbf?api-version=1.0&style=relative&zoom={z}&x={x}&y={y}"

// Create a vector tile source and add it to the map.
let source = VectorTileSource(options: [
    .tiles([trafficFlowUrl]),
    .maxSourceZoom(22)
])
map.sources.add(source)

// Create a layer for traffic flow lines.
let layer = LineLayer(
    source: source,
    options: [

        // The name of the data layer within the data source to pass into this rendering layer.
        .sourceLayer("Traffic flow"),

        // Color the roads based on the traffic_level property.
        .strokeColor(
            from: NSExpression(
                forAZMInterpolating: NSExpression(forKeyPath: "traffic_level"),
                curveType: .linear,
                parameters: nil,
                stops: NSExpression(forConstantValue: [
                    0: UIColor.red,
                    0.33: UIColor.yellow,
                    0.66: UIColor.green
                ])
            )
        ),

        // Scale the width of roads based on the traffic_level property.
        .strokeWidth(
            from: NSExpression(
                forAZMInterpolating: NSExpression(forKeyPath: "traffic_level"),
                curveType: .linear,
                parameters: nil,
                stops: NSExpression(forConstantValue: [
                    0: 6,
                    1: 1
                ])
            )
        )
    ]
)

// Add the traffic flow layer below the labels to make the map clearer.
map.layers.insertLayer(layer, below: "labels")

Schermopname van een kaart met in kleur gecodeerde weglijnen met verkeersstroomniveaus.

Verbinding maken een gegevensbron naar een laag

Gegevens worden op de kaart weergegeven met behulp van renderinglagen. Een of meer renderinglagen kunnen verwijzen naar één gegevensbron. Voor de volgende renderinglagen is een gegevensbron vereist:

  • Bellenlaag : geeft puntgegevens weer als geschaalde cirkels op de kaart.
  • Symboollaag: geeft puntgegevens weer als pictogrammen of tekst.
  • Heatmap-laag : geeft puntgegevens weer als een dichtheids heatmap.
  • Lijnlaag : een lijn weergeven en of het overzicht van veelhoeken weergeven.
  • Polygoonlaag : vult het gebied van een veelhoek met een effen kleur of afbeeldingspatroon.

De volgende code laat zien hoe u een gegevensbron maakt, deze toevoegt aan de kaart, GeoJSON-puntgegevens importeert vanaf een externe locatie in de gegevensbron en deze vervolgens verbindt met een bellenlaag.

// Create a data source.
let source = DataSource()

// Create a web url or a local file url
let url = URL(string: "URL_or_FilePath_to_GeoJSON_data")!
// Examples:
// let url = Bundle.main.url(forResource: "FeatureCollectionSample", withExtension: "geojson")!
// let url = URL(string: "yourdomain.com/path_to_feature_collection_sample")!

// Import the geojson data and add it to the data source.
source.importData(fromURL: url)

// Add data source to the map.
map.sources.add(source)

// Create a layer that defines how to render points in the data source and add it to the map.
let layer = BubbleLayer(source: source)
map.layers.addLayer(layer)

Er zijn andere renderinglagen die geen verbinding maken met deze gegevensbronnen, maar ze laden de gegevens rechtstreeks voor rendering.

  • Tegellaag - superimposeert een rastertegellaag boven op de kaart.

Eén gegevensbron met meerdere lagen

Meerdere lagen kunnen worden verbonden met één gegevensbron. Er zijn veel verschillende scenario's waarin deze optie nuttig is. Denk bijvoorbeeld aan het scenario waarin een gebruiker een veelhoek tekent. We moeten het veelhoekgebied weergeven en vullen wanneer de gebruiker punten toevoegt aan de kaart. Door een gestijlde lijn toe te voegen om de veelhoek te schetsen, kunt u de randen van de veelhoek gemakkelijker zien, terwijl de gebruiker tekent. Als u een afzonderlijke positie in de veelhoek handig wilt bewerken, kunnen we boven elke positie een greep toevoegen, zoals een speld of een markering.

Schermopname van een kaart met meerdere lagen die gegevens uit één gegevensbron weergeven.

In de meeste toewijzingsplatformen hebt u een veelhoekobject, een lijnobject en een speld nodig voor elke positie in de veelhoek. Wanneer de veelhoek wordt gewijzigd, moet u de lijn en pinnen handmatig bijwerken, wat snel complex kan worden.

Met Azure Kaarten hebt u alleen maar één veelhoek in een gegevensbron nodig, zoals wordt weergegeven in de volgende code.

// Create a data source and add it to the map.
let source = DataSource()
map.sources.add(source)

// Create a polygon and add it to the data source.
source.add(geometry: Polygon([
    CLLocationCoordinate2D(latitude: 33.15, longitude: -104.5),
    CLLocationCoordinate2D(latitude: 38.5, longitude: -113.5),
    CLLocationCoordinate2D(latitude: 43, longitude: -111.5),
    CLLocationCoordinate2D(latitude: 43.5, longitude: -107),
    CLLocationCoordinate2D(latitude: 43.6, longitude: -94)
]))

// Create a polygon layer to render the filled in area of the polygon.
let polygonLayer = PolygonLayer(
    source: source,
    options: [.fillColor(UIColor(red: 1, green: 165/255, blue: 0, alpha: 0.2))]
)

// Create a line layer for greater control of rendering the outline of the polygon.
let lineLayer = LineLayer(source: source, options: [
    .strokeColor(.orange),
    .strokeWidth(2)
])

// Create a bubble layer to render the vertices of the polygon as scaled circles.
let bubbleLayer = BubbleLayer(
    source: source,
    options: [
        .bubbleColor(.orange),
        .bubbleRadius(5),
        .bubbleStrokeColor(.white),
        .bubbleStrokeWidth(2)
    ]
)

// Add all layers to the map.
map.layers.addLayers([polygonLayer, lineLayer, bubbleLayer])

Tip

U kunt ook een methode gebruiken map.layers.insertLayer(_:below:) , waarbij de id of het exemplaar van een bestaande laag kan worden doorgegeven als een tweede parameter. Dit geeft aan dat de kaart de nieuwe laag moet invoegen die onder de bestaande laag wordt toegevoegd. Naast het doorgeven van een laag-id ondersteunt deze methode ook de volgende waarden.

  • "labels" - Hiermee wordt de nieuwe laag onder de kaartlabellagen ingevoegd.
  • "transit" - Hiermee voegt u de nieuwe laag toe onder de wegen- en transitlagen van de kaart.

Aanvullende informatie

Zie de volgende artikelen voor meer codevoorbeelden die u aan uw kaarten kunt toevoegen: