Migrating to v1
Move an app from a 0.x Wemap SDK to 1.0, step by step.
Overview
v1 replaces four things across every framework:
- Static singletons → per-instance sessions.
WemapCore.sharedandWemapMap.sharedare gone; aWemapCoreSDK/CoreSessionorWemapMapSDK/MapSessionloads the map data and is shared by the views and location sources of one screen. - Global mutable constants → immutable configs.
CoreConstants,MapConstants,ARConstantsand the VPS constants are replaced by value-typeConfigstructs, fixed at creation time. - Delegates →
AsyncStream. Every*Delegateprotocol on a manager or a location source is removed in favour of a read-only stream property. - Combine → Swift Concurrency. No public API returns an
AnyPublisherany more; calls areasyncand/orthrows.
Work through the steps in order. Each step leaves the project compiling, so you can stop and test between them. Steps 1–7 apply to every app; the rest depend on what your 0.x code uses — search your project for the symbols on the left.
| If your project contains | Also read |
|---|---|
VPSARKitLocationSource, GPSLocationSource, or any *Constants from a positioning SDK | 8 · positioning |
PackdataManaging, downloadPackdata(mapID:) | 9 · offline maps |
GeoARView, GeoARViewDelegate, ARConstants | 10 · GeoAR |
your own type conforming to LocationSource | 11 · custom location source |
| a symbol that still fails to compile after 1–11 | 12, then § "I'm getting this error" |
- Effort: a few hours for a map-only app; closer to a day for an app with VPS positioning or a custom location source.
- Toolchain: Xcode 26.0 / Swift 6.2 and iOS 15.0 are now the minimum — see Getting started § Requirements.
Tip: If you are migrating an Android app in parallel, the Android guide uses the same step numbering.
1 · Update the dependency
Rule: move to the latest 1.x release and raise your toolchain floor.
Take the version itself — and the transitive dependency versions that come with it — from the releases page. This guide deliberately does not repeat them, so that it stays correct as 1.x moves on.
Two floors changed in v1, and they block the build before anything else does:
- Xcode 26.0 / Swift 6.2. The SDKs ship as binary XCFrameworks, which only the toolchain that built them and newer can consume. SPM refuses the package outright; CocoaPods fails later, in the compiler.
- iOS 15.0 deployment target, raised from 13.0.
The Map SDK's public API now exposes MapLibre 6.x types, so a pinned older MapLibre will not satisfy it.
2 · Create a session
Rule: wherever you reached a singleton or passed a MapData, create one session per screen and pass it in.
// before
WemapMap.shared.getMapData(mapID: 19158, token: "TOKEN")
.sink(receiveCompletion: { _ in }) { mapData in
let mapView = MapView(frame: view.bounds)
mapView.mapData = mapData
}
.store(in: &cancellables)
// after
let session = try await MapSession(mapID: 19158, token: "TOKEN", config: SessionConfig(environment: .prod))
let mapView = MapView(frame: view.bounds, session: session, config: MapViewConfig())
Share the same session across a screen's WemapMapSDK/MapView, WemapGeoARSDK/GeoARView and location
sources — that is what keeps navigation, POI selection and user location consistent. A second map needs its own
session.
CoreSession(mapID:token:config:) and MapSession(mapID:token:config:) are both async throws; offline maps
use MapSession(offlineZip:config:) (see step 9).
Removed: WemapCore.shared, WemapCore.setEnvironment, WemapCore.setItinerariesEnvironment,
WemapMap.shared, WemapMap.getMapData(mapID:token:), ServiceFactory, DependencyManager.
Initializer mapping:
| v0.x | v1.0 |
|---|---|
MapView(frame:) + mapData | MapView(frame:session:config:) |
GeoARView(frame:options:) + mapData | GeoARView(frame:session:config:) |
VPSARKitLocationSource(mapData:) / (serviceURL:) | try VPSARKitLocationSource(session:config:) |
GPSLocationSource(mapData:) | GPSLocationSource(session:) |
SimulatorLocationSource(mapData:options:) / (options:) | SimulatorLocationSource(session:options:) |
| Interface Builder | mapView.configure(with:config:) / geoARView.configure(with:config:) |
Watch out: MapData is no longer public. Read map metadata from the session — session.mapID,
session.mapCenter, session.isVPSEnabled. MapView.mapData and GeoARView.mapData are gone, and
MapServicing with them — the session resolves map metadata itself.
3 · Pass configs instead of setting globals
Rule: every value you used to assign to a *Constants static is now a let property of a config struct,
built in one initializer call and passed at creation time. There is no global mutable configuration left.
// before
CoreConstants.itineraryRecalculationEnabled = false
MapConstants.staleStateTimeout = 10 // TimeInterval
// after
let session = try await MapSession(
mapID: 19158, token: "TOKEN",
config: SessionConfig(itineraryRecalculationEnabled: false, environment: .dev)
)
let mapView = MapView(frame: view.bounds, session: session, config: MapViewConfig(staleStateTimeout: .seconds(10)))
| v0.x | v1.0 | Passed to |
|---|---|---|
CoreConstants statics | SessionConfig | CoreSession.init / MapSession.init |
WemapCore.setEnvironment(_:) | SessionConfig.environment | CoreSession.init / MapSession.init |
WemapCore.setItinerariesEnvironment(_:) | SessionConfig.directionsEnvironment | CoreSession.init / MapSession.init |
MapConstants statics | MapViewConfig | MapView.init / configure(with:config:) |
ARConstants + ARConstants.DirectionalArrow | GeoARViewConfig + GeoARViewConfig.DirectionalArrow | GeoARView.init / configure |
VPSARKitConstants, VPSControllerConstants, StateManagerConstants | VPSConfig — see step 8 | VPSARKitLocationSource.init |
Renames and shape changes to expect while you move the values across:
MapViewConfig.staleStateTimeoutis aDispatchTimeInterval, not aTimeInterval.GeoARViewConfig.stepInstructionAltitudefixes the oldstepInstuctionAltitudespelling, andnavigationVisibilityDistanceis now optional.MapConstantskeeps onlywemapBlue;ARConstantsis no longer public at all.Environmentlostdomainandname.CoreConstants.itinerariesHost/itinerariesBaseURLwere stored and settable; theSessionConfigproperties that replace them are computed fromdirectionsEnvironment, so they can no longer disagree with it.
Watch out: every config property is let. Build the config you want in one init call — there is nothing to
assign to afterwards, by design.
4 · Update your Coordinate and level usage
Rule: WemapCoreSDK/Coordinate is an immutable struct built around CLLocationCoordinate2D — it no
longer wraps a CLLocation — and levels are a WemapCoreSDK/Levels value rather than [Float].
// before
let coordinate = Coordinate(location: someCLLocation, levels: [0, 1])
let heading = coordinate.direction
let location = coordinate.location
// after
let coordinate = Coordinate(coordinate2D: someCLLocation.coordinate, levels: .range(0...1))
let heading = coordinate.bearing
let location = coordinate.toLocation()
| v0.x | v1.0 |
|---|---|
levels: [Float] (empty meant outdoor) | levels: Levels (.outdoor by default) |
Coordinate(location:levels:heightFromFloor:heightFromGround:) | Coordinate(coordinate2D:levels:altitude:bearing:horizontalAccuracy:timestamp:heightFromFloor:heightFromGround:) |
direction | bearing |
location: CLLocation | toLocation() |
ShortStringConvertible / shortDescription | CustomCompactStringConvertible / compactDescription |
Levels has .outdoor, .single(_:) and .range(_:) (a ClosedRange<Float>), plus init(array:), union,
contains, intersects, intersection and diff. Segment.levels is a Levels too.
horizontalAccuracy is a stored CLLocationAccuracy and timestamp a stored Date.
Removed: cartesian, ecef, ecefToEnuRot, enuToEcefRot, ecefToEusRot, eusToEcefRot and the
copy(…) overloads.
compactDescription replaces shortDescription on Coordinate, Itinerary, ItinerarySearchRules,
NavigationInfo, NavigationOptions, PointOfInterest, PointOfInterestType, TravelMode,
ItineraryOptions and LineOptions.
Level moved from Core to the Map SDK and is a struct instead of an @objc final class; LevelData and
LevelUtils went with it. Import WemapMapSDK where you used to get Level from Core.
Watch out: toLocation() allocates a fresh CLLocation on every call — hold the result rather than calling
it in a loop.
5 · Replace delegates with AsyncStream
Rule: delete the delegate conformance and consume the stream of the same name in a Task.
// before
mapView.pointOfInterestManager.delegate = self
func pointOfInterestManager(_ manager: PointOfInterestManager, didSelectPointOfInterest poi: PointOfInterest) { … }
// after — take the stream out of the manager *before* the task, so the task captures the stream, not the manager
let selectionUpdates = mapView.pointOfInterestManager.selectionUpdates
observationTasks = [
Task { [weak self] in
for await update in selectionUpdates {
guard let self else {
return
}
handle(update)
}
}
]
| v0.x delegate | v1.0 streams |
|---|---|
LocationSourceDelegate | coordinates / attitudes / errors |
NavigationManagerDelegate | navigationEvents (NavigationEvent) / navigationInfoUpdates / errors |
PointOfInterestManagerDelegate | selectionUpdates (PointOfInterestSelectionUpdate) / touchedPOIs |
BuildingManagerDelegate | focusedBuildings / activeLevelChanges / errors |
UserLocationManagerDelegate, ARLocationManagerDelegate | coordinates / attitudes / errors |
MapViewDelegate | see step 7 |
VPSARKitLocationSourceDelegate | see step 8 |
Also removed: the publishers bridges — MapView.publishers, VPSARKitLocationSource.publishers,
MapViewDelegatePublishers, VPSARKitLocationSourceDelegatePublishers. coordinatePublisher is coordinates.
UserLocationManager and ARLocationManager now conform to the read-only UserLocationProviding, renamed
from LocationProviding.
Watch out: never write for await x in mapView.someManager.someStream. That captures the manager — and
through it the view — for as long as the task runs, so the owner's deinit never runs, and deinit is what
cancels the task: the leak keeps itself alive. Extract the stream into a local first, capture [weak self], and
return — not continue — once self is gone. Hold the tasks (observationTasks above) and cancel them on
teardown.
6 · Await instead of subscribing
Rule: an AnyPublisher-returning call is now async and/or throws and returns its value directly.
// before
mapView.navigationManager.startNavigation(to: destination)
.sink(receiveCompletion: { … }, receiveValue: { navigation in … })
.store(in: &cancellables)
// after
let navigation = try await mapView.navigationManager.startNavigation(to: destination)
Calls that changed shape: ItineraryProviding.itineraries(…), ruleNames(),
itinerariesInfoToMultipleDestinations(…), PointOfInterestServicing.pointsOfInterest(…),
PointOfInterestManaging.sortPOIsByGraphDistance(…) / sortPOIsByDuration(…),
ItineraryManager.searchRuleNames(), MapNavigationManaging.startNavigation(…),
ARNavigationManaging.startNavigation(…), VPSARKitLocationSource.isVPSAvailable(at:) and
distanceToVPSCoverage(from:).
Removed with Combine: Signal, EventPublisher, PassthroughRelay, CurrentValueRelay, Just.any(_:),
Empty.any(…), Empty.never(), Fail.any(…).
Renames and signature changes on the same call sites:
| v0.x | v1.0 |
|---|---|
ItineraryService, ItineraryServiceError | DirectionsService, DirectionsServiceError (gained graphUnavailable and requestFailed(code:reason:); noItinerariesFound gained reason) |
ItineraryServicing | renamed DirectionsServicing and no longer public |
ItineraryProviding.graph(id:), ruleNames(graphId:) | graph(), ruleNames() |
itineraries(…mapId:) | itineraries(…) — no mapId |
itinerariesInfoToMultipleDestinations(origin:pois:mapID:) | (origin:destinations:travelMode:searchRules:), taking [Coordinate] and returning [CoordinateWithItineraryInfo] — the POI-based call is now itinerariesInfoToMultiplePOIs(origin:pois:…) |
PointOfInterestServicing.pointsOfInterestList(mapID:limit:) | pointsOfInterest(limit:) |
PointOfInterestWithInfo (typealias) | PointOfInterestWithItineraryInfo |
PointOfInterestManaging.getPOIs() | getAllPOIs() |
PointOfInterestManager.SelectionMode | PointOfInterestSelectionMode |
ItineraryManager.itineraries, getItineraries(…) | drawnItineraries, computeItineraries(…) |
ItineraryManager.searchRuleNames(graphId:) | searchRuleNames() |
NavigationManaging.infoUpdatesTimeInterval | navigationInfoUpdatesInterval |
MapView.map (WemapMap) | removed with the type |
Building.isEqual(_:) / hash | Hashable / hashValue; levels is read-only |
Logger.d/i/v/e/f | same, plus a privacy parameter; Logger.category is read-only |
ItineraryManager.addItinerary(_:options:) returns Bool instead of (inserted:memberAfterInsert:), and
removeItinerary(_:) returns Bool instead of Itinerary?. startNavigation overloads take an additional
userTrackingMode, and their itineraryOptions parameter is optional — nil preserves the current options.
MapPointOfInterestManaging.selectPOI(…) and centerToPOI(…) take an optional zoom.
Watch out: the SDK builds in Swift 6 language mode. The view and manager surfaces are @MainActor without
@preconcurrency, so a call from a non-isolated context no longer compiles implicitly — hop to the main actor
explicitly. LocationSource, UserLocationProviding, ItineraryProviding and PointOfInterestServicing gained
a Sendable requirement (see step 11).
7 · Views: LoadPhase and non-optional managers
Rule: wait for the view with awaitLoaded() (or observe loadPhases), then use its managers without
optional handling.
// before
mapView.mapDelegate = self
func mapViewLoaded(_ mapView: MapView, style: MLNStyle, data: MapData) {
mapView.navigationManager?.startNavigation(…)
}
// after
try await mapView.awaitLoaded()
mapView.navigationManager.startNavigation(…) // no optional, no `if let`
MapViewDelegate is removed. MapView reports loading through loadPhase / loadPhases (LoadPhase) and
awaitLoaded(), and taps that selected no POI through touchedPoints. MapView.isLoaded and
MapView.mapDelegate are gone with it. mapViewLoaded(_:style:data:) has no replacement payload: MapData is
no longer public, and MapView.style is non-nil from .ready onward.
Every late-initialized member of both views is a plain non-optional property, and misuse is reported with a diagnostic naming the property instead of "Unexpectedly found nil while unwrapping an Optional value":
WemapMapSDK/MapView:session,config,pointOfInterestManager,navigationManager,buildingManager,itineraryManager,userLocationManagerWemapGeoARSDK/GeoARView:session,config,pointOfInterestManager,navigationManager,locationManager
map.navigationManager.startNavigation(…) is unaffected, but if let manager = map.navigationManager and
map.navigationManager?.… no longer compile — drop the optional handling and gate the access on awaitLoaded()
or loadPhases instead.
Failures are now reported. A map that fails to load settles .failed; in v0.x it logged
mapViewDidFailLoadingMap, told nobody, and left awaitLoaded() suspended forever. A points-of-interest
download failure settles .failed as well, and in that case every manager stays usable, exactly as before.
MapView.initialCamera sets the camera the map opens at, in place of the one derived from the map data. It is
handed over rather than applied — the camera needs a laid-out view — so set it before the view is laid out; a
later assignment is ignored and logged. MapView.isInitialCameraApplied / awaitInitialCamera() report when it
has been applied; it is not part of LoadPhase.
Watch out: isLoaded was true after a failure too, so its closest equivalent is !loadPhase.isLoading —
not loadPhase.isReady.
Watch out: one view of each kind per session. A session holds one map renderer and one AR renderer slot, so
a second MapView on the same session evicts the first, which keeps drawing while no manager drives it.
8 · If you use positioning (VPS or GPS)
Rule: construct the source with the session and a VPSConfig, and consume its streams instead of a delegate.
// before
VPSControllerConstants.backgroundScanDistanceThreshold = 20
let source = VPSARKitLocationSource(mapData: mapData)
source.vpsDelegate = self
// after
let source = try VPSARKitLocationSource(
session: session,
config: VPSConfig(controller: VPSControllerConfig(backgroundScanDistanceThreshold: 20))
)
let states = source.states // out of the source before the task, as in step 5
observationTask = Task { [weak self] in
for await state in states {
guard let self else {
return
}
handle(state)
}
}
VPSARKitLocationSource.init(session:config:) throws. VPSConfig composes VPSLocationSourceConfig,
VPSControllerConfig, VPSStateManagerConfig, VPSStaticPositionDetectorConfig and
VPSConveyingDetectorConfig — under the labels locationSource:, controller:, stateManager:,
staticPositionDetector: and conveyingDetector: — replacing VPSARKitConstants, VPSControllerConstants
and StateManagerConstants.
VPSARKitLocationSourceDelegate is removed in favour of states, scanStatuses, backgroundScanStatuses,
cameraTrackingStates, userLocalizationUpdates and errors. delegate, vpsDelegate, attitudeDelegate,
captureDelegate, observer and delegateQueue are gone with it.
Other changes:
| v0.x | v1.0 |
|---|---|
VPSARKitLocationSourceError.failedToConvertUIImageToPNGData | failedToConvertUIImageToData (and a new noVPSEndpoint case) |
VPSARKitLocationSourceObserver, willSendImage | removed |
DegradedPositioningReason.vpsTrackingInterrupted | removed |
TrackingState / WorldMappingStatus / DegradedPositioningReason.Reason / UIDeviceOrientation helpers description / isStable / isTracking | removed |
GPSLocationSource(mapData:) | GPSLocationSource(session:); isAvailable is read-only |
VPSARKitLocationSource no longer conforms to AttitudeSource, CameraCaptureProviding, ConveyingDetecting
or NavigationManagerInterceptor, and attitudeAccuracy / buffersPublisher were removed. GeoJsonItinerary
moved here from Core.
9 · If you use offline maps
Rule: get a packdata service from the session, then open the downloaded package as a session.
// before
let manager: PackdataManaging = …
manager.downloadPackdata(mapID: 19158)
.flatMap { manager.loadMapData(fromZip: $0.fileURL) }
.sink { mapData in … }
.store(in: &cancellables)
// after
let service = MapSession.createPackdataService(mapID: 19158, environment: .prod)
let packdata = try await service.downloadPackdata()
let session = try await MapSession(offlineZip: packdata.fileURL)
| v0.x | v1.0 |
|---|---|
PackdataManaging | PackdataServicing, from MapSession.createPackdataService(mapID:environment:) |
downloadPackdata(mapID:), isNewPackdataAvailable(mapID:eTag:) | downloadPackdata(), isNewPackdataAvailable(eTag:) — mapID is bound at construction |
loadMapData(fromZip:) | MapSession(offlineZip:config:) |
Packdata still carries fileURL, eTag, version and fileName.
10 · If you use GeoAR
Rule: same as the map — session in, loadPhase out, GeoARViewConfig for the tunables.
GeoARViewDelegate is removed, together with GeoARView.isLoaded and GeoARView.viewDelegate. GeoARView
reports loading through loadPhase / loadPhases (LoadPhase) and awaitLoaded(), the same surface as
MapView — so geoARViewLoaded(_:mapData:) has no replacement callback at all.
ARConstants and ARConstants.DirectionalArrow became GeoARViewConfig and GeoARViewConfig.DirectionalArrow — see
step 3. ARPointOfInterestManaging.isFixedSize moved off PointOfInterestManager onto the protocol.
UIInterfaceOrientation.description was removed.
SceneKit is no longer part of the AR view's API. GeoARView is a UIView instead of an SCNView, and
GeoARView.camera, .geoScene and .rootNode are gone with GeoCamera, GeoEntity and GeoNode — the scene
graph is now an implementation detail, so a future renderer change costs you nothing. The options parameter went
with them: GeoARView(frame:session:config:), GeoAR(session:config:makeARView:) and the makeARView closure
take no [String: Any]. Nothing replaces the removed members; if you were reading the scene graph, tell us what
for.
Watch out: on the Interface Builder path the config goes into the configure(with:config:) call itself. There
is no settable config property to assign after the fact, and configure only runs once — a second call is ignored.
11 · If you implement a custom LocationSource
Rule: publish coordinates through streams instead of a delegate. The assignment point does not change.
// before
final class MyLocationSource: LocationSource {
weak var delegate: LocationSourceDelegate?
var supportsHeading: Bool { true }
func report(_ c: Coordinate) { delegate?.locationSource(self, didUpdateCoordinate: c) }
}
// after
@MainActor
final class MyLocationSource: LocationSource {
static var isAvailable: Bool { true }
var coordinates: AsyncStream<Coordinate> { … }
var attitudes: AsyncStream<Attitude> { … }
var errors: AsyncStream<Error> { … }
var supportsAttitude: Bool { true }
var isStarted: Bool { … }
func start() { … }
func stop() { … }
}
| v0.x | v1.0 |
|---|---|
LocationSource.delegate (LocationSourceDelegate) | coordinates / attitudes / errors |
LocationSource.supportsHeading | supportsAttitude |
SimulationOptions.simulateHeading | simulateAttitude |
Assign the source exactly as before — mapView.userLocationManager.locationSource for the map, and
geoARView.locationManager.locationSource for AR.
WemapCoreSDK/LocationSource is @MainActor and refines AnyObject, Sendable, so the conformance carries
Sendable for you — but the type has to actually satisfy it. UserLocationProviding, ItineraryProviding and
PointOfInterestServicing gained the same requirement.
Watch out: a source your app starts stays your app's to stop. The SDK reference-counts its own start and stop requests, so a view disabling its location component no longer stops a source it did not start.
12 · Symbols that are no longer public API
Rule: these were public in 0.x and are not part of the supported surface any more. There is no
customer-facing replacement for any of them — if your app uses one, plan the migration off it.
Some exist only for cross-module needs inside the SDK now. They are excluded from this documentation, and reaching one fails to compile with "is inaccessible due to '@_spi' protection level":
MapData, CoreConstants, DataStore, Graph with Vertex / Edge, LocationProcessor,
NavigationManager, PointOfInterestManager, ItineraryProvider, ServiceBase / RemoteServiceBase /
LocalServiceBase, FileServicing, AttitudeSource with SystemAttitudeSource, ConveyingDetecting with
ConveyingBuffer, NavigationRendering, PointOfInterestRendering, NavigationManagerInterceptor,
CameraCaptureDelegate / CameraCaptureProviding with ViewParameters, InstructionKey, Inclination,
Status, HTTPMethod / HTTPHeaders / HTTPHeader / URLRequestConvertible, Attribute, Validator,
Math, GeoUtils, GeoConstants, JSONBodyEncoder / QueryEncoder, Zip with ZipError, VisualDebugger,
MapPointOfInterestManaging.defaultZoom, Coordinate.equals(…), ARConstants, LocalPose with MatF4x4,
and the GeoARView camera-provider members.
Removed outright, with no replacement: toDispatchTimeInterval(), toUnix(), allPerform(_:),
filterPolygons(), filterMultiPolygons(), localize(args:locale:comment:), Polygon.distance(to:),
MultiPolygon.distance(to:), Polygon.init(center:radius:), JSONDecoder.create(keyEncodingStrategy:) /
JSONEncoder.create(keyEncodingStrategy:), DecodingError.Context.init(debugDescription:underlyingError:),
Logger.elapsedTimePrefix(), GitInfo, PointOfInterest.customerID, Itinerary.legsSegments,
Itinerary.toGeoJsonItinerary(), the legsSteps setter, NavigationInstructions.direction, and
DispatchQueue.computation / navigation / network.
Changes that compile but behave differently
Nothing in this list produces a compiler error. Check each one against your app.
| Change | What to do |
|---|---|
isLoaded had been true after a failure too | its equivalent is !loadPhase.isLoading, not loadPhase.isReady |
A map that fails to load settles .failed | awaitLoaded() throws instead of suspending forever — handle it |
A coordinate's time is encoded in Unix seconds | if you persisted or forwarded encoded coordinates, re-check the unit |
Coordinate.bearing of -1 is encoded now (it means 359°) | it is no longer dropped as an invalid sentinel; accuracy is sent only when positive |
MapCameraState equality is epsilon-based | a camera you built compares equal to the one the map reports |
| The user location indicator greys the moment tracking is lost | it no longer stays blue for staleStateTimeout |
| The attribution sheet is presented from the hosting view controller | found up the responder chain, not the app's topmost controller |
startNavigation sets userTrackingMode itself | it follows with heading when navigation starts |
A second MapView or GeoARView on one session evicts the first | one view of each kind per session; a second map needs its own |
"I'm getting this error"
| Error | Go to |
|---|---|
cannot find 'WemapCore' in scope | Step 2 |
cannot find 'WemapMap' in scope | Step 2 |
'mapData' is inaccessible due to '@_spi' protection level | Step 2 |
argument 'session' missing | Step 2 |
cannot assign to property: 'environment' is a 'let' constant | Step 3 |
cannot find 'CoreConstants' / 'MapConstants' / 'ARConstants' in scope | Step 3 |
value of type 'Coordinate' has no member 'direction' | Step 4 |
cannot convert value of type '[Float]' to expected argument type 'Levels' | Step 4 |
value of type 'Coordinate' has no member 'location' | Step 4 |
cannot find 'shortDescription' in scope | Step 4 |
value of type 'AnyPublisher<…>' has no member 'sink' after a rename | Step 6 |
call is 'async' but is not marked with 'await' | Step 6 |
main actor-isolated property … can not be referenced from a nonisolated context | Step 6 |
cannot find type 'MapViewDelegate' in scope | Step 7 |
initializer for conditional binding must have Optional type, not 'NavigationManager' | Step 7 |
call can throw but is not marked with 'try' on VPSARKitLocationSource.init | Step 8 |
cannot find type 'VPSARKitLocationSourceDelegate' in scope | Step 8 |
cannot find type 'PackdataManaging' in scope | Step 9 |
type 'MyLocationSource' does not conform to protocol 'Sendable' | Step 11 |
is inaccessible due to '@_spi' protection level | Step 12 |
cannot find 'customerID' / 'legsSegments' / 'GitInfo' in scope | Step 12 |
Reference: renamed, moved and removed API
| v0.x symbol | v1.0 replacement | Step |
|---|---|---|
ARConstants | GeoARViewConfig | 3 |
Coordinate.direction | Coordinate.bearing | 4 |
Coordinate.location | Coordinate.toLocation() | 4 |
CoreConstants | SessionConfig | 3 |
GeoARViewDelegate | loadPhase / loadPhases / awaitLoaded() | 10 |
ItineraryManager.getItineraries(…) | computeItineraries(…) | 6 |
ItineraryService | DirectionsService | 6 |
Level (Core) | Level (Map SDK), now a struct | 4 |
LocationSource.supportsHeading | supportsAttitude | 11 |
MapConstants.staleStateTimeout | MapViewConfig.staleStateTimeout (DispatchTimeInterval) | 3 |
MapViewDelegate | loadPhase / loadPhases / touchedPoints | 7 |
PackdataManaging | PackdataServicing | 9 |
PointOfInterestManaging.getPOIs() | getAllPOIs() | 6 |
ShortStringConvertible | CustomCompactStringConvertible | 4 |
VPSARKitConstants | VPSConfig | 8 |
WemapCore.shared | CoreSession | 2 |
WemapMap.getMapData(mapID:token:) | MapSession(mapID:token:config:) | 2 |
| … | … |
Getting help
Sample apps: wemap-sdk-sample-apps-ios. Anything unclear or missing here — contact the Wemap team.