Skip to content

Commit f4ccd88

Browse files
Upgrade iOS SDK to v200.7 (#90)
* Upgrade arcgis sdk * Upgrade arcgis sdk + create MapContentView * Fix few issues after upgrading sdk * Fix few issues after upgrading sdk * Clean code * fix build * reformat code * Update CustomLocationProvider.swift * Fix location indicator example --------- Co-authored-by: Julian Bissekkou <[email protected]>
1 parent 35ba0b2 commit f4ccd88

File tree

15 files changed

+385
-291
lines changed

15 files changed

+385
-291
lines changed

arcgis_map_sdk_ios/ios/arcgis_map_sdk_ios.podspec

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,7 @@ A new Flutter project.
1414
s.source = { :path => '.' }
1515
s.source_files = 'arcgis_map_sdk_ios/Sources/**/*'
1616
s.dependency 'Flutter'
17-
s.dependency 'ArcGIS-Runtime-Toolkit-iOS'
18-
s.platform = :ios, '13.0'
17+
s.platform = :ios, '16.0'
1918

2019
# Flutter.framework does not contain a i386 slice.
2120
s.pod_target_xcconfig = { 'DEFINES_MODULE' => 'YES', 'EXCLUDED_ARCHS[sdk=iphonesimulator*]' => 'i386' }

arcgis_map_sdk_ios/ios/arcgis_map_sdk_ios/Package.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,19 +6,19 @@ import PackageDescription
66
let package = Package(
77
name: "arcgis_map_sdk_ios",
88
platforms: [
9-
.iOS("14.0")
9+
.iOS("16.0")
1010
],
1111
products: [
1212
.library(name: "arcgis-map-sdk-ios", targets: ["arcgis_map_sdk_ios"])
1313
],
1414
dependencies: [
15-
.package(url: "https://github.com/Esri/arcgis-runtime-ios", .upToNextMinor(from: "100.15.0")),
15+
.package(url: "https://github.com/Esri/arcgis-maps-sdk-swift", .upToNextMinor(from: "200.7.0")),
1616
],
1717
targets: [
1818
.target(
1919
name: "arcgis_map_sdk_ios",
2020
dependencies: [
21-
.product(name: "ArcGIS", package: "arcgis-runtime-ios")
21+
.product(name: "ArcGIS", package: "arcgis-maps-sdk-swift")
2222
]
2323
),
2424
]

arcgis_map_sdk_ios/ios/arcgis_map_sdk_ios/Sources/arcgis_map_sdk_ios/ArcgisMapView.swift

Lines changed: 195 additions & 203 deletions
Large diffs are not rendered by default.
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
//
2+
// Created by Julian Bissekkou on 27.11.23.
3+
//
4+
5+
import Foundation
6+
import ArcGIS
7+
8+
final class CustomLocationProvider: LocationProvider {
9+
private var locationContinuation: AsyncStream<Location>.Continuation?
10+
private var headingContinuation: AsyncStream<Double>.Continuation?
11+
12+
13+
// Exposed stream
14+
var locations: AsyncStream<Location> {
15+
AsyncStream { @Sendable continuation in
16+
self.locationContinuation = continuation
17+
continuation.onTermination = { _ in
18+
self.locationContinuation = nil
19+
}
20+
}
21+
}
22+
23+
var headings: AsyncStream<Double> {
24+
AsyncStream { continuation in
25+
self.headingContinuation = continuation
26+
continuation.onTermination = { @Sendable _ in
27+
self.headingContinuation = nil
28+
}
29+
}
30+
}
31+
32+
// Push location from outside
33+
public func setNewLocation(_ position: UserPosition) {
34+
let loc = Location(
35+
position: position.latLng.toAGSPoint(),
36+
horizontalAccuracy: position.accuracy ?? 0,
37+
verticalAccuracy: position.accuracy ?? 0,
38+
speed: position.velocity ?? 0,
39+
course: position.heading ?? 0,
40+
isLastKnown: false
41+
)
42+
locationContinuation?.yield(loc)
43+
if let heading = position.heading {
44+
headingContinuation?.yield(heading)
45+
}
46+
}
47+
}
48+

arcgis_map_sdk_ios/ios/arcgis_map_sdk_ios/Sources/arcgis_map_sdk_ios/GraphicsParser.swift

Lines changed: 32 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,10 @@ class GraphicsParser {
1616
self.registrar = registrar
1717
}
1818

19-
func parse(dictionary: Dictionary<String, Any>) throws -> [AGSGraphic] {
19+
func parse(dictionary: Dictionary<String, Any>) throws -> [Graphic] {
2020
let type = dictionary["type"] as! String
2121

22-
let newGraphics: [AGSGraphic]
22+
let newGraphics: [Graphic]
2323
switch (type) {
2424
case "point":
2525
newGraphics = try! parsePoint(dictionary)
@@ -31,26 +31,29 @@ class GraphicsParser {
3131
throw ParseException(message: "Unknown graphic type: \(type)")
3232
}
3333

34-
let attributes = dictionary["attributes"] as? Dictionary<String, Any>
35-
if let attributes = attributes {
36-
newGraphics.forEach {
37-
$0.attributes.addEntries(from: attributes)
34+
// Apply attributes to each graphic, if present
35+
if let attributes = dictionary["attributes"] as? [String: Any] {
36+
newGraphics.forEach { graphic in
37+
for (key, value) in attributes {
38+
graphic.setAttributeValue(value, forKey: key)
39+
}
3840
}
3941
}
42+
4043
return newGraphics
4144
}
4245

43-
private func parsePoint(_ dictionary: [String: Any]) throws -> [AGSGraphic] {
46+
private func parsePoint(_ dictionary: [String: Any]) throws -> [Graphic] {
4447
let point: LatLng = try! JsonUtil.objectOfJson(dictionary["point"] as! Dictionary<String, Any>)
4548

46-
let graphic = AGSGraphic()
49+
let graphic = Graphic()
4750
graphic.geometry = point.toAGSPoint()
4851
graphic.symbol = try! parseSymbol(dictionary["symbol"] as! Dictionary<String, Any>)
4952

5053
return [graphic]
5154
}
5255

53-
private func parsePolyline(_ dictionary: [String: Any]) throws -> [AGSGraphic] {
56+
private func parsePolyline(_ dictionary: [String: Any]) throws -> [Graphic] {
5457
let payload: PathPayload = try! JsonUtil.objectOfJson(dictionary)
5558

5659
return try payload.paths.map { coordinates in
@@ -59,28 +62,28 @@ class GraphicsParser {
5962
throw ParseException(message: "Size of coordinates need to be at least 2. Got \(array)")
6063
}
6164
if(array.count > 2) {
62-
return AGSPoint(x: array[0], y: array[1], z: array[2], spatialReference: .wgs84())
65+
return Point(x: array[0], y: array[1], z: array[2], spatialReference: .wgs84)
6366
}
64-
return AGSPoint(x: array[0], y: array[1], spatialReference: .wgs84())
67+
return Point(x: array[0], y: array[1], spatialReference: .wgs84)
6568
}
6669

67-
let graphic = AGSGraphic()
68-
graphic.geometry = AGSPolyline(points: points)
70+
let graphic = Graphic()
71+
graphic.geometry = Polyline(points: points)
6972
graphic.symbol = try! parseSymbol(dictionary["symbol"] as! Dictionary<String, Any>)
7073

7174
return graphic
7275
}
7376
}
7477

75-
private func parsePolygon(_ dictionary: [String: Any]) throws -> [AGSGraphic] {
78+
private func parsePolygon(_ dictionary: [String: Any]) throws -> [Graphic] {
7679
let payload: PolygonPayload = try! JsonUtil.objectOfJson(dictionary)
7780

7881
return payload.rings.map { ring in
79-
let graphic = AGSGraphic()
82+
let graphic = Graphic()
8083
let points = ring.map { coordinate in
81-
AGSPoint(x: coordinate[0], y: coordinate[1], spatialReference: .wgs84())
84+
Point(x: coordinate[0], y: coordinate[1], spatialReference: .wgs84)
8285
}
83-
graphic.geometry = AGSPolygon(points: points)
86+
graphic.geometry = Polygon(points: points)
8487
graphic.symbol = try! parseSymbol(dictionary["symbol"] as! Dictionary<String, Any>)
8588

8689
return graphic
@@ -89,7 +92,7 @@ class GraphicsParser {
8992

9093
// region symbol parsing
9194

92-
func parseSymbol(_ dictionary: [String: Any]) throws -> AGSSymbol {
95+
func parseSymbol(_ dictionary: [String: Any]) throws -> Symbol {
9396
let type = dictionary["type"] as! String;
9497
switch (type) {
9598
case "simple-marker":
@@ -105,48 +108,48 @@ class GraphicsParser {
105108
}
106109
}
107110

108-
private func parseSimpleMarkerSymbol(_ dictionary: [String: Any]) -> AGSSymbol {
111+
private func parseSimpleMarkerSymbol(_ dictionary: [String: Any]) -> Symbol {
109112
let payload: SimpleMarkerSymbolPayload = try! JsonUtil.objectOfJson(dictionary)
110113

111-
let symbol = AGSSimpleMarkerSymbol()
114+
let symbol = SimpleMarkerSymbol()
112115
symbol.color = payload.color.toUIColor()
113116
symbol.size = payload.size
114-
symbol.outline = AGSSimpleLineSymbol(
117+
symbol.outline = SimpleLineSymbol(
115118
style: .solid,
116119
color: payload.outlineColor.toUIColor(),
117120
width: payload.outlineWidth
118121
)
119122
return symbol
120123
}
121124

122-
private func parseSimpleFillMarkerSymbol(_ dictionary: [String: Any]) -> AGSSymbol {
125+
private func parseSimpleFillMarkerSymbol(_ dictionary: [String: Any]) -> Symbol {
123126
let payload: SimpleFillSymbolPayload = try! JsonUtil.objectOfJson(dictionary)
124127

125-
let symbol = AGSSimpleFillSymbol()
128+
let symbol = SimpleFillSymbol()
126129
symbol.color = payload.fillColor.toUIColor()
127130

128-
let outline = AGSSimpleLineSymbol()
131+
let outline = SimpleLineSymbol()
129132
outline.width = payload.outlineWidth
130133
outline.color = payload.outlineColor.toUIColor()
131134
symbol.outline = outline
132135

133136
return symbol
134137
}
135138

136-
private func parsePictureMarkerSymbol(_ dictionary: [String: Any]) -> AGSSymbol {
139+
private func parsePictureMarkerSymbol(_ dictionary: [String: Any]) -> Symbol {
137140
let payload: PictureMarkerSymbolPayload = try! JsonUtil.objectOfJson(dictionary)
138141

139142
if(!payload.assetUri.isWebUrl()) {
140143
let uiImage = getFlutterUiImage(payload.assetUri)
141-
let symbol = AGSPictureMarkerSymbol(image: uiImage!)
144+
let symbol = PictureMarkerSymbol(image: uiImage!)
142145
symbol.width = payload.width
143146
symbol.height = payload.height
144147
symbol.offsetX = payload.xOffset
145148
symbol.offsetY = payload.yOffset
146149
return symbol
147150
}
148151

149-
let symbol = AGSPictureMarkerSymbol(url: URL(string: payload.assetUri)!)
152+
let symbol = PictureMarkerSymbol(url: URL(string: payload.assetUri)!)
150153
symbol.width = payload.width
151154
symbol.height = payload.height
152155
symbol.offsetX = payload.xOffset
@@ -161,9 +164,9 @@ class GraphicsParser {
161164
return UIImage(named: path!)
162165
}
163166

164-
private func parseSimpleLineSymbol(_ dictionary: [String: Any]) -> AGSSymbol {
167+
private func parseSimpleLineSymbol(_ dictionary: [String: Any]) -> Symbol {
165168
let payload: SimpleLineSymbolPayload = try! JsonUtil.objectOfJson(dictionary)
166-
let symbol = AGSSimpleLineSymbol()
169+
let symbol = SimpleLineSymbol()
167170

168171
if let color = payload.color {
169172
symbol.color = color.toUIColor()

arcgis_map_sdk_ios/ios/arcgis_map_sdk_ios/Sources/arcgis_map_sdk_ios/ManualLocationDataSource.swift

Lines changed: 0 additions & 22 deletions
This file was deleted.
Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
//
2+
// Created by Tarek Tolba on 29/04/2025.
3+
//
4+
5+
import SwiftUI
6+
import ArcGIS
7+
import CoreLocation
8+
9+
10+
struct MapContentView: View {
11+
@ObservedObject var viewModel: MapViewModel
12+
13+
init(viewModel: MapViewModel) {
14+
self.viewModel = viewModel
15+
}
16+
17+
var body: some View {
18+
MapViewReader { mapViewProxy in
19+
MapView(
20+
map: viewModel.map,
21+
viewpoint: viewModel.viewpoint,
22+
graphicsOverlays: [viewModel.defaultGraphicsOverlay]
23+
)
24+
.attributionBarHidden(viewModel.attributionBarHidden)
25+
.locationDisplay(viewModel.locationDisplay)
26+
.contentInsets(viewModel.contentInsets)
27+
.interactionModes(viewModel.interactionModes)
28+
.onViewpointChanged(kind: .centerAndScale) { newViewpoint in
29+
viewModel.viewpoint = newViewpoint
30+
}
31+
.onScaleChanged { scale in
32+
viewModel.onScaleChanged?(scale)
33+
}
34+
.onVisibleAreaChanged { polygon in
35+
viewModel.onVisibleAreaChanged?(polygon)
36+
}
37+
.onChange(of: viewModel.map.basemap?.loadStatus) { newValue in
38+
if let newValue {
39+
viewModel.onLoadStatusChanged?(newValue)
40+
}
41+
}
42+
.task {
43+
// Store the mapViewProxy for external access
44+
viewModel.mapViewProxy = mapViewProxy
45+
viewModel.onViewInit?();
46+
}
47+
.onDisappear {
48+
viewModel.stopLocationDataSource()
49+
// Clear the mapViewProxy reference when view disappears
50+
viewModel.mapViewProxy = nil
51+
}
52+
.ignoresSafeArea(edges: .all)
53+
}
54+
}
55+
}
56+
57+
58+
class MapViewModel: ObservableObject {
59+
let map = Map()
60+
let locationDisplay = LocationDisplay()
61+
62+
@Published var viewpoint: Viewpoint
63+
@Published var mapViewProxy: MapViewProxy?
64+
@Published var attributionBarHidden: Bool = false
65+
@Published var contentInsets: EdgeInsets = EdgeInsets()
66+
@Published var interactionModes: MapViewInteractionModes = .all
67+
@Published var defaultGraphicsOverlay = GraphicsOverlay()
68+
69+
var onScaleChanged: ((Double) -> Void)?
70+
var onVisibleAreaChanged: ((Polygon) -> Void)?
71+
var onLoadStatusChanged: ((LoadStatus) -> Void)?
72+
var onViewInit: (() -> Void)?
73+
74+
init(viewpoint : Viewpoint) {
75+
self.viewpoint = viewpoint
76+
}
77+
78+
/// Stops the location data source.
79+
func stopLocationDataSource() {
80+
Task {
81+
await locationDisplay.dataSource.stop()
82+
}
83+
}
84+
}

arcgis_map_sdk_ios/ios/arcgis_map_sdk_ios/Sources/arcgis_map_sdk_ios/Models/AnimationOptions.swift

Lines changed: 0 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -13,19 +13,3 @@ struct AnimationOptions: Codable {
1313
var animationCurve: String
1414
}
1515

16-
extension AnimationOptions {
17-
func arcgisAnimationCurve() -> AGSAnimationCurve {
18-
switch animationCurve {
19-
case "linear":
20-
return .linear
21-
case "easeIn":
22-
return .easeInCirc
23-
case "easeOut":
24-
return .easeOutCirc
25-
case "easeInOut":
26-
return .easeInOutCirc
27-
default:
28-
return .linear
29-
}
30-
}
31-
}

arcgis_map_sdk_ios/ios/arcgis_map_sdk_ios/Sources/arcgis_map_sdk_ios/Models/LatLng.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ struct LatLng: Codable {
1515
}
1616

1717
extension LatLng {
18-
func toAGSPoint() -> AGSPoint {
19-
AGSPoint(x: longitude, y: latitude, spatialReference: .wgs84())
18+
func toAGSPoint() -> Point {
19+
Point(x: longitude, y: latitude, spatialReference: .wgs84)
2020
}
2121
}

0 commit comments

Comments
 (0)