Skip to content

Commit

Permalink
Migrate Turf GeoJSON usage to GeoJSONObject and JSONValue (#715)
Browse files Browse the repository at this point in the history
* Fixed typo in file name

* Turf v2.0.0-rc.2

* Updated Turf GeoJSON integration

Co-authored-by: Andrew Hershberger <[email protected]>
  • Loading branch information
1ec5 and macdrevx authored Sep 29, 2021
1 parent 312a5f9 commit de3800d
Show file tree
Hide file tree
Showing 39 changed files with 373 additions and 195 deletions.
4 changes: 2 additions & 2 deletions Apps/Apps.xcworkspace/xcshareddata/swiftpm/Package.resolved
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,8 @@
"repositoryURL": "https://github.com/mapbox/turf-swift.git",
"state": {
"branch": null,
"revision": "555458bd67acce7322c513ddd3647c9a904f4197",
"version": "2.0.0-rc.1"
"revision": "007896bb945432d4683e114fcf2f089edff4ceeb",
"version": "2.0.0-rc.2"
}
}
]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ public class AnimateGeoJSONLineExample: UIViewController, ExampleProtocol {
let updatedLine = Feature(geometry: .lineString(LineString(currentCoordinates)))
self.routeLineSource.data = .feature(updatedLine)
try! self.mapView.mapboxMap.style.updateGeoJSONSource(withId: self.sourceIdentifier,
geoJSON: updatedLine)
geoJSON: .feature(updatedLine))
}
}

Expand Down
6 changes: 3 additions & 3 deletions Apps/Examples/Examples/All Examples/AnimateLayerExample.swift
Original file line number Diff line number Diff line change
Expand Up @@ -108,12 +108,12 @@ public class AnimateLayerExample: UIViewController, ExampleProtocol {

// Identify the new coordinate to animate to, and calculate
// the bearing between the new coordinate and the following coordinate.
var geoJSON = Feature.init(geometry: Geometry.point(Point(coordinate)))
geoJSON.properties = ["bearing": coordinate.direction(to: nextCoordinate)]
var geoJSON = Feature(geometry: .point(Point(coordinate)))
geoJSON.properties = ["bearing": .number(coordinate.direction(to: nextCoordinate))]

// Update the airplane source layer with the new coordinate and bearing.
try! self.mapView.mapboxMap.style.updateGeoJSONSource(withId: self.airplaneSymbol.identifier,
geoJSON: geoJSON)
geoJSON: .feature(geoJSON))

runCount += 1

Expand Down
8 changes: 4 additions & 4 deletions Apps/Examples/Examples/All Examples/FeatureStateExample.swift
Original file line number Diff line number Diff line change
Expand Up @@ -192,11 +192,11 @@ public class FeatureStateExample: UIViewController, ExampleProtocol {

// Extract the earthquake feature from the queried features
if let earthquakeFeature = queriedfeatures.first?.feature,
case .number(.double(let earthquakeIdDouble)) = earthquakeFeature.identifier,
case .number(let earthquakeIdDouble) = earthquakeFeature.identifier,
case .point(let point) = earthquakeFeature.geometry,
let magnitude = earthquakeFeature.properties?["mag"] as? Double,
let place = earthquakeFeature.properties?["place"] as? String,
let timestamp = earthquakeFeature.properties?["time"] as? Double {
case let .number(magnitude) = earthquakeFeature.properties?["mag"],
case let .string(place) = earthquakeFeature.properties?["place"],
case let .number(timestamp) = earthquakeFeature.properties?["time"] {

let earthquakeId = Int(earthquakeIdDouble).description

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ public class FeaturesAtPointExample: UIViewController, ExampleProtocol {
switch result {
case .success(let queriedfeatures):
if let firstFeature = queriedfeatures.first?.feature?.properties,
let stateName = firstFeature["STATE_NAME"] as? String {
case let .string(stateName) = firstFeature["STATE_NAME"] {
self?.showAlert(with: "You selected \(stateName)")
}
case .failure(let error):
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ public class LineGradientExample: UIViewController, ExampleProtocol {
var featureCollection: FeatureCollection?
do {
let data = try Data(contentsOf: filePath)
featureCollection = try GeoJSON.parse(FeatureCollection.self, from: data)
featureCollection = try JSONDecoder().decode(FeatureCollection.self, from: data)
} catch {
print("Error parsing data: \(error)")
}
Expand Down
2 changes: 1 addition & 1 deletion Apps/Examples/Examples/All Examples/LiveDataExample.swift
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ final class LiveDataExample: UIViewController, ExampleProtocol {
self.parseGeoJSON { result in
switch result {
case .success(let feature):
try! self.mapView.mapboxMap.style.updateGeoJSONSource(withId: self.sourceId, geoJSON: feature)
try! self.mapView.mapboxMap.style.updateGeoJSONSource(withId: self.sourceId, geoJSON: .feature(feature))
case .failure(let error):
print("Error: \(error.localizedDescription)")
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ public class MultipleGeometriesExample: UIViewController, ExampleProtocol {

do {
let data = try Data(contentsOf: filePath)
featureCollection = try GeoJSON.parse(FeatureCollection.self, from: data)
featureCollection = try JSONDecoder().decode(FeatureCollection.self, from: data)
} catch {
print("Error parsing data: \(error)")
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -152,16 +152,16 @@ class SymbolClusteringExample: UIViewController, ExampleProtocol {
// Check whether the feature has values for `ASSETNUM` and `LOCATIONDETAIL`. These properties
// come from the fire hydrant dataset and indicate that the selected feature is not clustered.
if let selectedFeatureProperties = queriedFeatures.first?.feature?.properties,
let featureInformation = selectedFeatureProperties["ASSETNUM"] as? String,
let location = selectedFeatureProperties["LOCATIONDETAIL"] as? String {
case let .string(featureInformation) = selectedFeatureProperties["ASSETNUM"],
case let .string(location) = selectedFeatureProperties["LOCATIONDETAIL"] {
self?.showAlert(withTitle: "Hydrant \(featureInformation)", and: "\(location)")
// If the feature is a cluster, it will have `point_count` and `cluster_id` properties. These are assigned
// when the cluster is created.
} else if let selectedFeatureProperties = queriedFeatures.first?.feature?.properties,
let pointCount = selectedFeatureProperties["point_count"] as? Int,
let clusterId = selectedFeatureProperties["cluster_id"] as? Int {
case let .number(pointCount) = selectedFeatureProperties["point_count"],
case let .number(clusterId) = selectedFeatureProperties["cluster_id"] {
// If the tap landed on a cluster, pass the cluster ID and point count to the alert.
self?.showAlert(withTitle: "Cluster ID \(clusterId)", and: "There are \(pointCount) points in this cluster")
self?.showAlert(withTitle: "Cluster ID \(Int(clusterId))", and: "There are \(Int(pointCount)) points in this cluster")
}
case .failure(let error):
self?.showAlert(withTitle: "An error occurred: \(error.localizedDescription)", and: "Please try another hydrant")
Expand Down
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ Mapbox welcomes participation and contributions from everyone.
* `TileRegionLoadOptions` init now takes a `Geometry` instead of a `MapboxCommon.Geometry`. ([#711](https://github.com/mapbox/mapbox-maps-ios/pull/711))
* `CameraAnimationsManager.options` has been removed. Use `MapboxMap.cameraBounds` and `MapboxMap.setCameraBounds(with:)` instead. ([#712](https://github.com/mapbox/mapbox-maps-ios/pull/712))
* `MapboxMap.setCameraBounds(for:)` has been renamed to `.setCameraBounds(with:)` ([#712](https://github.com/mapbox/mapbox-maps-ios/pull/712))
* Requires [Turf v2.0.0-rc.2](https://github.com/mapbox/turf-swift/releases/tag/v2.0.0-rc.2). ([#715](https://github.com/mapbox/mapbox-maps-ios/pull/715))
* Renames `Style.updateGeoJSONSource<T: GeoJSONObject>(withId:geoJSON:)` to `Style.updateGeoJSONSource(withId:geoJSON:)`. Instead of passing in the expected GeoJSON object type, you perform pattern matching on the return value using `case let`. ([#715](https://github.com/mapbox/mapbox-maps-ios/pull/715))

### Features ✨ and improvements 🏁

Expand Down
2 changes: 1 addition & 1 deletion MapboxMaps.podspec
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,6 @@ Pod::Spec.new do |m|
m.dependency 'MapboxCoreMaps', '10.0.0-rc.9.1'
m.dependency 'MapboxCommon', '19.0.0'
m.dependency 'MapboxMobileEvents', '1.0.4'
m.dependency 'Turf', '2.0.0-rc.1'
m.dependency 'Turf', '2.0.0-rc.2'

end
4 changes: 2 additions & 2 deletions Package.resolved
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,8 @@
"repositoryURL": "https://github.com/mapbox/turf-swift.git",
"state": {
"branch": null,
"revision": "555458bd67acce7322c513ddd3647c9a904f4197",
"version": "2.0.0-rc.1"
"revision": "007896bb945432d4683e114fcf2f089edff4ceeb",
"version": "2.0.0-rc.2"
}
}
]
Expand Down
2 changes: 1 addition & 1 deletion Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ let package = Package(
.package(name: "MapboxCoreMaps", url: "https://github.com/mapbox/mapbox-core-maps-ios.git", .exact("10.0.0-rc.9.1")),
.package(name: "MapboxMobileEvents", url: "https://github.com/mapbox/mapbox-events-ios.git", .exact("1.0.4")),
.package(name: "MapboxCommon", url: "https://github.com/mapbox/mapbox-common-ios.git", .exact("19.0.0")),
.package(name: "Turf", url: "https://github.com/mapbox/turf-swift.git", .exact("2.0.0-rc.1")),
.package(name: "Turf", url: "https://github.com/mapbox/turf-swift.git", .exact("2.0.0-rc.2")),
.package(name: "CocoaImageHashing", url: "https://github.com/ameingast/cocoaimagehashing", .exact("1.9.0"))
],
targets: [
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,9 @@ public struct CircleAnnotation: Annotation {
internal var feature: Turf.Feature {
var feature = Turf.Feature(geometry: geometry)
feature.identifier = .string(id)
var properties = [String: Any?]()
properties["layerProperties"] = layerProperties
properties["userInfo"] = userInfo
var properties = JSONObject()
properties["layerProperties"] = JSONValue(rawValue: layerProperties)
properties["userInfo"] = userInfo.flatMap(JSONValue.init(rawValue:))
feature.properties = properties
return feature
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,9 @@ public struct PointAnnotation: Annotation {
internal var feature: Turf.Feature {
var feature = Turf.Feature(geometry: geometry)
feature.identifier = .string(id)
var properties = [String: Any?]()
properties["layerProperties"] = layerProperties
properties["userInfo"] = userInfo
var properties = JSONObject()
properties["layerProperties"] = JSONValue(rawValue: layerProperties)
properties["userInfo"] = userInfo.flatMap(JSONValue.init(rawValue:))
feature.properties = properties
return feature
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,9 @@ public struct PolygonAnnotation: Annotation {
internal var feature: Turf.Feature {
var feature = Turf.Feature(geometry: geometry)
feature.identifier = .string(id)
var properties = [String: Any?]()
properties["layerProperties"] = layerProperties
properties["userInfo"] = userInfo
var properties = JSONObject()
properties["layerProperties"] = JSONValue(rawValue: layerProperties)
properties["userInfo"] = userInfo.flatMap(JSONValue.init(rawValue:))
feature.properties = properties
return feature
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,9 @@ public struct PolylineAnnotation: Annotation {
internal var feature: Turf.Feature {
var feature = Turf.Feature(geometry: geometry)
feature.identifier = .string(id)
var properties = [String: Any?]()
properties["layerProperties"] = layerProperties
properties["userInfo"] = userInfo
var properties = JSONObject()
properties["layerProperties"] = JSONValue(rawValue: layerProperties)
properties["userInfo"] = userInfo.flatMap(JSONValue.init(rawValue:))
feature.properties = properties
return feature
}
Expand Down
21 changes: 9 additions & 12 deletions Sources/MapboxMaps/Foundation/Extensions/Turf/Feature.swift
Original file line number Diff line number Diff line change
Expand Up @@ -18,18 +18,14 @@ extension Turf.Feature {
*/
switch feature.identifier {
case let identifier as NSNumber:
if String(cString: identifier.objCType) == "q" {
self.identifier = .number(.int(identifier.intValue))
} else {
self.identifier = .number(.double(identifier.doubleValue))
}
self.identifier = .number(identifier.doubleValue)
case let identifier as String:
self.identifier = FeatureIdentifier.string(identifier)
self.identifier = .string(identifier)
default:
break
}

properties = feature.properties
properties = JSONObject(rawValue: feature.properties)
}

/// Initialize a `Turf.Feature` with a `Point`.
Expand Down Expand Up @@ -84,9 +80,7 @@ extension MapboxCommon.Feature {
// Features may or may not have an identifier. If they have one,
// it is either a number or string value.
switch feature.identifier {
case let .number(.int(intId)):
identifier = NSNumber(value: intId)
case let .number(.double(doubleId)):
case let .number(doubleId):
identifier = NSNumber(value: doubleId)
case let .string(stringId):
identifier = NSString(string: stringId)
Expand All @@ -98,10 +92,13 @@ extension MapboxCommon.Feature {
#endif
}

let geometry = MapboxCommon.Geometry(geometry: feature.geometry)
// A null geometry is valid GeoJSON but not supported by MapboxCommon.
// The closest thing would be an empty GeometryCollection.
let nonNullGeometry = feature.geometry ?? .geometryCollection(.init(geometries: []))
let geometry = MapboxCommon.Geometry(geometry: nonNullGeometry)

self.init(identifier: identifier,
geometry: geometry,
properties: (feature.properties as? [String: NSObject]) ?? [:])
properties: (feature.properties?.rawValue as? [String: NSObject]) ?? [:])
}
}
2 changes: 1 addition & 1 deletion Sources/MapboxMaps/Style/Style.swift
Original file line number Diff line number Diff line change
Expand Up @@ -180,7 +180,7 @@ public class Style {
///
/// - Attention: This method is only effective with sources of `GeoJSONSource`
/// type, and cannot be used to update other source types.
public func updateGeoJSONSource<T: GeoJSONObject>(withId id: String, geoJSON: T) throws {
public func updateGeoJSONSource(withId id: String, geoJSON: GeoJSONObject) throws {
guard let sourceInfo = allSourceIdentifiers.first(where: { $0.id == id }),
sourceInfo.type == .geoJson else {
fatalError("updateGeoJSONSource: Source with id '\(id)' is not a GeoJSONSource.")
Expand Down
Loading

0 comments on commit de3800d

Please sign in to comment.