Migrate from SkyPath SDK 3.x to 4.0
This guide is provided to ease the transition of existing applications using SkyPath v3.x to v4.0 APIs.
v4.0 renames the turbulence API to observations, replaces the mutable dataQuery with a validated fetchConfig, and moves start/simulation/analytics onto dedicated entry points.
Most renamed APIs ship an @available(*, unavailable, renamed:) shim, so Xcode will point at the replacement with a fix-it. Work through the sections below in order and the compiler will find the rest.
1. Initialization
- Build an
AuthConfig from your existing start(...) arguments — airline becomes companyId.
- Replace the
start(...) call with initialize(with:completion:).
- Delete any
stop() calls; the SDK does not need to be stopped.
- Replace
StartError handling with GeneralError (or the generic SPError).
- Remove any reads of
SkyPath.env.
SkyPath.shared.start(apiKey: key, airline: icao, userId: userId, env: env) { error in }
let config = AuthConfig(apiKey: key, companyId: icao, userId: userId, env: env)
SkyPath.shared.initialize(with: config) { error in }
| 3.x | 4.0 |
|---|
start(apiKey:airline:userId:env:completion:) | initialize(with:completion:) |
stop() | Removed — stopping the SDK is no longer available |
StartError | Removed — errors are GeneralError / other SPError types |
SkyPath.env | Removed |
2. Fetch configuration
- Rename the type
DataQuery to FetchConfig everywhere.
- Replace every
SkyPath.shared.dataQuery.<field> = value assignment with updateFetchConfig { $0.<field> = value } — fetchConfig is now read-only.
- Group fields you used to set one by one into a single
updateFetchConfig closure, so validation and the fetch check run once.
- Add
try and error handling — updateFetchConfig(_:) and setFetchConfig(_:) throw a QueryError on a malformed polygon/viewport or an unsupported aircraftICAO.
- Rename the three toggles:
dataUpdateEnabled, dataUpdateInBackgroundIsEnabled, peerEnabled.
- Delete
fetchData(...), fetchingStatus(...) and updateDate(of:) calls.
SkyPath.shared.dataQuery.polygon = polygon
SkyPath.shared.dataQuery.types = [.turbulence]
do {
try SkyPath.shared.updateFetchConfig {
$0.polygon = polygon
$0.types = [.observations]
$0.aircraftICAO = "B737"
}
} catch {
print(error)
}
do {
try SkyPath.shared.setFetchConfig(FetchConfig(polygon: polygon))
} catch {
print(error)
}
| 3.x | 4.0 |
|---|
SkyPath.dataQuery (settable) | SkyPath.fetchConfig (read-only) + updateFetchConfig(_:) / setFetchConfig(_:) |
DataQuery | FetchConfig |
SkyPath.dataUpdateEnabled | SkyPath.isFetchEnabled |
SkyPath.dataUpdateInBackgroundIsEnabled | SkyPath.isBackgroundFetchEnabled |
SkyPath.peerEnabled | SkyPath.isPeerEnabled |
fetchData(refresh:types:) | Removed — data is fetched automatically; change fetchConfig instead |
fetchingStatus(for:dataType:) | Removed |
updateDate(of:) | Removed — use SkyPath.dataUpdatedAt |
fetchData(refresh:types:) was a public API and has no replacement: there is no way to trigger a
fetch manually any more. The SDK fetches on its own schedule and re-evaluates whenever fetchConfig
changes, so remove any "refresh data" button or pull-to-refresh that called it.
3. Data types
- Rename the type
DataTypeOptions to DataType everywhere.
- Rename the case
.turbulence to .observations.
- Change every
DataTypeOptions value to a Set<DataType> literal — types, viewportTypes, and your own properties.
- Replace
DataTypeOptions.all, .asArray and .rawValue usages with an explicit Set<DataType>.
- Replace
DataAreaType.any with .route, .viewport or .all.
SkyPath.shared.dataQuery.types = [.turbulence, .oneLayer]
if DataTypeOptions.forecast.enabled { ... }
try SkyPath.shared.updateFetchConfig { $0.types = [.observations, .oneLayer] }
if DataType.forecast.enabled { ... }
| 3.x | 4.0 |
|---|
DataTypeOptions | DataType |
DataTypeOptions.turbulence | DataType.observations |
DataTypeOptions.all / .asArray / .rawValue | Removed — use a Set<DataType> literal |
DataAreaType.any | Removed — use .route, .viewport, or .all |
DataType.forecast still requires .oneLayer to also be in types, and entitlement via DataType.forecast.enabled.
4. Observations (was Turbulence)
- Rename the call
turbulence(with:) to observations(with:).
- Rename the types
TurbulenceQuery → ObservationsQuery and TurbulenceItem → ObservationsItem everywhere, including your own properties, arrays and function signatures.
- Update
QueryResult<TurbulenceItem> to QueryResult<ObservationsItem>.
- Update
TurbulenceCluster.turbulence and .nearestMaxSevTurbulence call sites — they now hand back ObservationsItem.
- Rename
TurbulenceItemable.turbulenceItem to asTurbulenceItem.
| 3.x | 4.0 |
|---|
SkyPath.turbulence(with:) | SkyPath.observations(with:) |
TurbulenceQuery | ObservationsQuery |
TurbulenceItem | ObservationsItem |
QueryResult<TurbulenceItem> | QueryResult<ObservationsItem> |
TurbulenceCluster.turbulence / .nearestMaxSevTurbulence | Now [ObservationsItem] / ObservationsItem? |
Array<TurbulenceItem>.geoJSON(withType:) | Array<ObservationsItem>.geoJSON(withType:) |
TurbulenceItemable.turbulenceItem | asTurbulenceItem (now returns ObservationsItem) |
5. Aircraft
- Delete all uses of the
Aircraft and AircraftSize types — they are no longer public.
- Replace
SkyPath.aircraft = ... with updateFetchConfig { $0.aircraftICAO = "B737" }.
- Delete
aircrafts() calls; there is no list of supported aircraft any more.
- Replace
aircraft(byId:) validation with a do/catch around updateFetchConfig — an unsupported ICAO throws.
- Read the current value from
SkyPath.fetchConfig.aircraftICAO instead of SkyPath.aircraft.
if let aircraft = SkyPath.shared.aircraft(byId: "B737") {
SkyPath.shared.aircraft = aircraft
}
do {
try SkyPath.shared.updateFetchConfig { $0.aircraftICAO = "B737" }
} catch {
print(error)
}
| 3.x | 4.0 |
|---|
SkyPath.aircraft | SkyPath.fetchConfig.aircraftICAO (default "B737") |
SkyPath.aircrafts() | Removed |
SkyPath.aircraft(byId:) | Removed — set aircraftICAO and handle the thrown error |
Aircraft, AircraftSize | Removed |
6. Notifications
- Delete
notifications(with:) calls and move that logic into didReceiveNotification(_:), starting monitoring with startMonitoringNotifications(with:).
- Rename
NotificationResult.turbulence to .observations.
- Make
NotificationQuery.minSev non-optional — remove the ? and drop nil assignments; the default is now .light.
- Delete
switchToBeamOnDistanceFromRoute, excludeOwnTimeSpan and tiles from your NotificationQuery setup.
- Remove any
NotificationResultType.tiles branches.
let result = try SkyPath.shared.notifications(with: query).get()
SkyPath.shared.startMonitoringNotifications(with: query)
| 3.x | 4.0 |
|---|
SkyPath.notifications(with:) | Removed — startMonitoringNotifications(with:) + didReceiveNotification(_:) |
NotificationResult.turbulence | NotificationResult.observations |
NotificationQuery.minSev: TurbulenceSeverity? | minSev: TurbulenceSeverity, default .light |
NotificationQuery.switchToBeamOnDistanceFromRoute | Removed — beam mode kicks in automatically when far from the route line |
NotificationQuery.excludeOwnTimeSpan | Removed |
NotificationQuery.tiles / NotificationResultType.tiles | Removed |
7. Recording state
- Replace
inPosition, isHorizontal and inNoise reads with a single SkyPath.recordingState check.
- Replace the
didUpdateRecordingStatus(to:) / didChangeDevicePosition(_:horizontal:) delegate methods with didUpdateRecordingState(to:) — see §9 Delegate.
- Map your pilot-facing messages onto the four
RecordingState cases.
Both 3.x callbacks collapse into didUpdateRecordingState(to:), and state == .recording carries what
each of them used to report:
- what
didUpdateRecordingStatus(to: true) reported is now state == .recording;
- what
didChangeDevicePosition(inPosition:horizontal:) reported is now inPosition == (state == .recording)
and horizontal == (state == .horizontal).
So if you handled both, move both bodies into the single method and derive the old booleans from state.
switch SkyPath.shared.recordingState {
case .recording, .notInPosition, .horizontal, .noise: break
}
func didUpdateRecordingState(to state: RecordingState) { }
| 3.x | 4.0 |
|---|
SkyPath.inPosition | SkyPath.recordingState == .recording |
SkyPath.isHorizontal | SkyPath.recordingState == .horizontal |
SkyPath.inNoise | SkyPath.recordingState == .noise |
8. App events
- Replace
setMapLayer(enabled:) with reportAppEvent(.mapLayer(enabled:)).
- Replace
notifiedTurbulenceSeverity(_:coordinate:altFt:dataSource:) with reportAppEvent(.notifiedTurbulence(severity:coordinate:altFt:dataSource:)).
SkyPath.shared.setMapLayer(enabled: true)
SkyPath.shared.notifiedTurbulenceSeverity(sev, coordinate: coord, altFt: alt, dataSource: source)
SkyPath.shared.reportAppEvent(.mapLayer(enabled: true))
SkyPath.shared.reportAppEvent(.notifiedTurbulence(severity: sev, coordinate: coord, altFt: alt, dataSource: source))
| 3.x | 4.0 |
|---|
setMapLayer(enabled:) | reportAppEvent(.mapLayer(enabled:)) |
notifiedTurbulenceSeverity(_:coordinate:altFt:dataSource:) | reportAppEvent(.notifiedTurbulence(severity:coordinate:altFt:dataSource:)) |
9. Delegate
- Implement all available
SkyPathDelegate methods — there are no default implementations any more, so a missing one is a compile error.
- Rename
didReceiveNewTurbulenceData(areaType:) to didReceiveNewObservationsData(areaType:).
- Merge
didFailToFetchNewData(with:type:) and locationManagerDidFail(withError:) into didFail(with:dataType:). dataType is optional: it carries the failing DataType for data-fetch errors and is nil for everything else (authorization, token refresh, location).
- Delete the six removed callbacks listed below — the SDK no longer calls them.
The 4.0 protocol is exactly: didReceiveNewObservationsData(areaType:), didReceiveNewOneLayer(areaType:), didFail(with:dataType:), didReceiveNotification(_:), didUpdateRecordingState(to:).
func didFailToFetchNewData(with error: SPError, type: DataTypeOptions) { }
func locationManagerDidFail(withError error: Error) { }
func didFail(with error: SPError, dataType: DataType?) {
switch dataType {
case .observations, .oneLayer: reloadTurbulenceLayer()
case .forecast: reloadForecastLayer()
case nil: break
default: break
}
}
| 3.x | 4.0 |
|---|
didReceiveNewTurbulenceData(areaType:) | didReceiveNewObservationsData(areaType:) |
didFailToFetchNewData(with:type:) | didFail(with:dataType:) |
locationManagerDidFail(withError:) | didFail(with:dataType:) (dataType is nil) |
didUpdateRecordingStatus(to:) / didChangeDevicePosition(_:horizontal:) | didUpdateRecordingState(to:) |
detectedTurbulence(_:) | Removed |
serverReachabilityUpdated(to:) | Removed |
didUpdateLowPowerMode(_:) | Removed |
didUpdateFetchingStatus(to:areaType:dataType:) | Removed |
didUpdateConfig() | Removed |
didUpdatePeers(discovered:connected:) | Removed |
10. Severity colors
- Rename
TurbulenceSeverity.none to .smooth everywhere, including switch cases.
- Define your own colors for the severity levels — colors were removed from the SDK. Use the reference palette from the Data page.
- Repoint
.color, .borderColor, .colorOpacity and .colorWithOpacity call sites at your own colors.
| 3.x | 4.0 |
|---|
TurbulenceSeverity.none | TurbulenceSeverity.smooth |
.color, .borderColor, .colorOpacity, .colorWithOpacity | Removed — provide your own |
11. Logging
- Replace
SkyPath.logger.printLevel = ... with SkyPath.loggerLevel = ....
- Replace
SkyPath.logger.exportLogs(...) with SkyPath.exportLogs(...).
- Delete every other
logger usage — the Logger type is no longer public.
| 3.x | 4.0 |
|---|
SkyPath.logger.printLevel | SkyPath.loggerLevel |
SkyPath.logger.exportLogs(notifyOnQueue:completion:) | SkyPath.exportLogs(notifyOnQueue:completion:) |
LoggingLevel | PrintLevel |
Logger, logger.isEnabled, .logsDirectory, .maximumNumberOfLogFiles, .rollingFrequency | Removed |
12. Flight
- Rename
Flight.fnum to Flight.num.
- Change
Flight(dep:dest:fnum:fnumManual:) to Flight(dep:dest:num:) — the fnumManual argument is gone.
- Remove reads of
Flight.id, .depLat, .depLng, .destLat, .destLng; keep those values on your own model if you need them.
- Remove observers of the
didUpdateFlight notification.
| 3.x | 4.0 |
|---|
Flight.fnum | Flight.num |
Flight(dep:dest:fnum:fnumManual:) | Flight(dep:dest:num:) |
Flight.id, .fnumManual, .depLat, .depLng, .destLat, .destLng | Removed |
Notification.Name.didUpdateFlight | Removed |
13. Testing & simulation
- Insert
.testing between SkyPath.shared and every simulation call — the methods themselves keep their names and signatures.
- Keep these calls on the staging environment only (
env: .staging(serverUrl: nil) in AuthConfig).
SkyPath.shared.enableSimulation(true)
SkyPath.shared.simulatedLocation(location)
SkyPath.shared.testing.enableSimulation(true)
SkyPath.shared.testing.simulatedLocation(location)
| 3.x | 4.0 |
|---|
SkyPath.enableSimulation(_:) | SkyPath.testing.enableSimulation(_:) |
SkyPath.simulatedLocation(_:) | SkyPath.testing.simulatedLocation(_:) |
SkyPath.enablePushSimulated(_:) | SkyPath.testing.enablePushSimulated(_:) |
SkyPath.simulateTurbulence(sev:) | SkyPath.testing.simulateTurbulence(sev:) |
SkyPath.simulateBadLocation(_:) | SkyPath.testing.simulateBadLocation(_:) |
SkyPath.simulateBadLocation (property) | SkyPath.testing.simulateBadLocation |
14. Errors
- Remove the four deleted
QueryError cases from your switch statements.
- Add
invalidRoute where you handle polygon/route problems.
- Handle the two new
GeneralError cases if you switch exhaustively: unauthorized(message:) (HTTP 401) and location(error:).
3.x QueryError case | 4.0 |
|---|
altRangeNotRoundToThousandFeet | Removed |
polygonTooManyCoordinates | Removed — use invalidPolygon |
invalidCoordinates | Removed — use invalidPolygon |
dataQueryInvalid(message:) | Removed — use invalidPolygon / invalidRoute / general(error:) |
| — | invalidRoute added |
15. Removed with no replacement
- Move local-notification scheduling into your app using Apple's
UserNotifications framework.
- Replace
Tile usages with the plain String tile keys still returned by QueryResult.tiles and accepted by ObservationsQuery.tiles / excludeTiles.
- Delete any UI driven by
serverReachable or lowPowerMode.
| 3.x | 4.0 |
|---|
SPLocalNotificationManager | Removed — use UserNotifications directly |
Tile, Itemable.tile | Removed — use String tile keys |
SkyPath.serverReachable | Removed — reachability status is no longer available |
SkyPath.lowPowerMode | Removed — low power mode status is no longer available |
Aircraft, AircraftSize | Removed — see §5 Aircraft |
Logger, LoggingLevel | Removed — see §11 Logging |
StartError | Removed — see §1 Initialization |