Skip to content

Commit 5bc0284

Browse files
Fix/camera bug fixes (#90)
* feat: task based camera * fix: modern concurrency camera * fix: modern concurrency camera * Update MapViewCoordinatorCameraTests.swift Co-authored-by: Ian Wagner <[email protected]> * Correcting task sleep * Adds docs, reverts structure for private * Adds docs, reverts structure for private * Additional camera fixes and improvements --------- Co-authored-by: Ian Wagner <[email protected]>
1 parent f0ad51b commit 5bc0284

File tree

2 files changed

+33
-48
lines changed

2 files changed

+33
-48
lines changed

Sources/MapLibreSwiftUI/MapViewCoordinator.swift

Lines changed: 27 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -182,10 +182,13 @@ MLNMapViewDelegate {
182182

183183
// Cancel any existing camera update completion task.
184184
cameraUpdateTask?.cancel()
185-
cameraUpdateContinuation = nil
186185

187186
cameraUpdateTask = Task { @MainActor in
188187
return await withCheckedContinuation { continuation in
188+
// Clean up the continuation if it was already set.
189+
cameraUpdateContinuation?.resume()
190+
cameraUpdateContinuation = nil
191+
189192
// Store the continuation to be resumed in mapViewDidBecomeIdle
190193
cameraUpdateContinuation = continuation
191194

@@ -234,35 +237,27 @@ MLNMapViewDelegate {
234237

235238
mapView.userTrackingMode = .follow
236239

237-
mapView.setZoomLevel(zoom, animated: false)
240+
mapView.zoomLevel = zoom
238241
mapView.direction = direction
239242

240243
mapView.minimumPitch = pitch
241244
mapView.maximumPitch = pitch
242245
mapView.minimumPitch = pitchRange.rangeValue.lowerBound
243246
mapView.maximumPitch = pitchRange.rangeValue.upperBound
244-
245247
} else {
246248
mapView.setUserTrackingMode(.follow, animated: animated) {
247249
guard mapView.userTrackingMode == .follow else {
248250
// Exit early if the user tracking mode is no longer set to follow
249251
return
250252
}
251253

254+
mapView.zoomLevel = zoom
255+
mapView.direction = direction
256+
257+
mapView.minimumPitch = pitch
258+
mapView.maximumPitch = pitch
252259
mapView.minimumPitch = pitchRange.rangeValue.lowerBound
253260
mapView.maximumPitch = pitchRange.rangeValue.upperBound
254-
let camera = mapView.camera
255-
camera.heading = direction
256-
camera.pitch = pitch
257-
258-
let altitude = MLNAltitudeForZoomLevel(
259-
zoom,
260-
pitch,
261-
mapView.camera.centerCoordinate.latitude,
262-
mapView.frame.size
263-
)
264-
camera.altitude = altitude
265-
mapView.setCamera(camera, animated: animated)
266261
}
267262
}
268263
case let .trackingUserLocationWithHeading(zoom: zoom, pitch: pitch, pitchRange: pitchRange):
@@ -272,32 +267,26 @@ MLNMapViewDelegate {
272267
// Needs to be non-animated or else it messes up following
273268

274269
mapView.userTrackingMode = .followWithHeading
275-
mapView.setZoomLevel(zoom, animated: false)
270+
271+
mapView.zoomLevel = zoom
272+
276273
mapView.minimumPitch = pitch
277274
mapView.maximumPitch = pitch
278275
mapView.minimumPitch = pitchRange.rangeValue.lowerBound
279276
mapView.maximumPitch = pitchRange.rangeValue.upperBound
280-
281277
} else {
282278
mapView.setUserTrackingMode(.followWithHeading, animated: animated) {
283279
guard mapView.userTrackingMode == .followWithHeading else {
284280
// Exit early if the user tracking mode is no longer set to followWithHeading
285281
return
286282
}
287283

284+
mapView.zoomLevel = zoom
285+
286+
mapView.minimumPitch = pitch
287+
mapView.maximumPitch = pitch
288288
mapView.minimumPitch = pitchRange.rangeValue.lowerBound
289289
mapView.maximumPitch = pitchRange.rangeValue.upperBound
290-
let camera = mapView.camera
291-
292-
let altitude = MLNAltitudeForZoomLevel(
293-
zoom,
294-
pitch,
295-
mapView.camera.centerCoordinate.latitude,
296-
mapView.frame.size
297-
)
298-
camera.altitude = altitude
299-
camera.pitch = pitch
300-
mapView.setCamera(camera, animated: animated)
301290
}
302291
}
303292
case let .trackingUserLocationWithCourse(zoom: zoom, pitch: pitch, pitchRange: pitchRange):
@@ -307,36 +296,32 @@ MLNMapViewDelegate {
307296
// so let's do something else instead.
308297
// Needs to be non-animated or else it messes up following
309298

310-
mapView.setZoomLevel(zoom, animated: false)
299+
mapView.zoomLevel = zoom
300+
311301
mapView.minimumPitch = pitch
312302
mapView.maximumPitch = pitch
313303
mapView.minimumPitch = pitchRange.rangeValue.lowerBound
314304
mapView.maximumPitch = pitchRange.rangeValue.upperBound
315-
316305
} else {
317306
mapView.setUserTrackingMode(.followWithCourse, animated: animated) {
318307
guard mapView.userTrackingMode == .followWithCourse else {
319308
// Exit early if the user tracking mode is no longer set to followWithCourse
320309
return
321310
}
322311

312+
mapView.zoomLevel = zoom
313+
314+
mapView.minimumPitch = pitch
315+
mapView.maximumPitch = pitch
323316
mapView.minimumPitch = pitchRange.rangeValue.lowerBound
324317
mapView.maximumPitch = pitchRange.rangeValue.upperBound
325-
326-
let camera = mapView.camera
327-
328-
let altitude = MLNAltitudeForZoomLevel(
329-
zoom,
330-
pitch,
331-
mapView.camera.centerCoordinate.latitude,
332-
mapView.frame.size
333-
)
334-
camera.altitude = altitude
335-
camera.pitch = pitch
336-
mapView.setCamera(camera, animated: animated)
337318
}
338319
}
339320
case let .rect(boundingBox, padding):
321+
mapView.minimumPitch = 0
322+
mapView.maximumPitch = 0
323+
mapView.direction = 0
324+
340325
mapView.setVisibleCoordinateBounds(boundingBox,
341326
edgePadding: padding,
342327
animated: animated,

Tests/MapLibreSwiftUITests/MapViewCoordinator/MapViewCoordinatorCameraTests.swift

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -174,8 +174,8 @@ final class MapViewCoordinatorCameraTests: XCTestCase {
174174
.setCalled(1)
175175

176176
verify(maplibreMapView)
177-
.setZoomLevel(.value(10), animated: .value(false))
178-
.called(1)
177+
.zoomLevel(newValue: .value(10))
178+
.setCalled(1)
179179
}
180180

181181
@MainActor func testUserTrackingWithCourseCameraUpdate() async throws {
@@ -219,8 +219,8 @@ final class MapViewCoordinatorCameraTests: XCTestCase {
219219
.setCalled(1)
220220

221221
verify(maplibreMapView)
222-
.setZoomLevel(.value(10), animated: .value(false))
223-
.called(1)
222+
.zoomLevel(newValue: .value(10))
223+
.setCalled(1)
224224
}
225225

226226
@MainActor func testUserTrackingWithHeadingUpdate() async throws {
@@ -264,8 +264,8 @@ final class MapViewCoordinatorCameraTests: XCTestCase {
264264
.setCalled(1)
265265

266266
verify(maplibreMapView)
267-
.setZoomLevel(.value(10), animated: .value(false))
268-
.called(1)
267+
.zoomLevel(newValue: .value(10))
268+
.setCalled(1)
269269
}
270270

271271
// TODO: Test Rect & Showcase once we build it!

0 commit comments

Comments
 (0)