Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions Sources/MapConductorForMapbox/MapboxMapHost.swift
Original file line number Diff line number Diff line change
Expand Up @@ -218,6 +218,7 @@ public final class MapboxMapHost: MapViewCoordinatorBase<MapboxViewState> {
controller.registerOverlayController(polygonController)
controller.registerOverlayController(groundImageController)
controller.registerOverlayController(rasterController)
controller.clearOverlaysHandler = { [weak self] in await self?.clearOverlays() }

let overlayScope = MapOverlayScope()
self.overlayScope = overlayScope
Expand Down Expand Up @@ -303,6 +304,17 @@ public final class MapboxMapHost: MapViewCoordinatorBase<MapboxViewState> {
}
}

/// android-sdk の `clearOverlays()` と同じく、各オーバーレイのコントローラを空にする。
/// `controller.clearOverlaysHandler` から呼ばれる。
func clearOverlays() async {
await markerController?.clear()
await polylineController?.clear()
await polygonController?.clear()
await groundImageController?.clear()
await circleController?.clear()
await rasterController?.clear()
}

public func unbind() {
// 登録した capability を取り下げる。レジストリの持ち主は state で、ビューより長生きするため、
// ここで外さないと破棄済みのコントローラを掴んだまま残る。
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,13 @@ final class MapboxViewController: MapViewControllerProtocol {
self.holder = AnyMapViewHolder(typedHolder)
}

func clearOverlays() async {}
/// ``clearOverlays()`` の中身。オーバーレイのコントローラはホストが持っているので、
/// ホストが生成時に設定する(android-sdk と同じく、各コントローラの `clear()` を呼ぶ)。
var clearOverlaysHandler: (@MainActor () async -> Void)?

func clearOverlays() async {
await clearOverlaysHandler?()
}

func setCameraMoveStartListener(listener: OnCameraMoveHandler?) { cameraMoveStartListener = listener }
func setCameraMoveListener(listener: OnCameraMoveHandler?) { cameraMoveListener = listener }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,13 @@ final class MapboxGroundImageController: SlottedOverlayController {

private var groundImageSubscriptions: [String: AnyCancellable] = [:]
private var groundImageStatesById: [String: GroundImageState] = [:]
/// `clear()` の時点で送られていた一式。同じ一式が送り直されている間は描かない。
///
/// core の `OverlayCollector` と振る舞いをそろえるため。あちらは clear 後も一式を覚えていて、
/// 同じインスタンスの再送では何もせず、顔ぶれが変わったか作り直された state が来たときだけ
/// 全部を描き直す。これが無いと、SwiftUI が body を再評価するたび(clear の直後にも来る)に
/// 消したはずの画像が戻っていた。
private var clearedStates: [String: GroundImageState]?
/// スタイル読み込み待ちの取り込み。捨てずに保留し、`onStyleLoaded` で流す。
/// 「なぜ待つ必要があるか」は `DeferredUntilReady` の説明にある。
private lazy var styleGate = DeferredUntilReady<[GroundImageState]> { [weak self] states in
Expand All @@ -34,6 +41,12 @@ final class MapboxGroundImageController: SlottedOverlayController {
}

func syncGroundImages(_ groundImages: [GroundImage]) {
if let cleared = clearedStates {
let resent = groundImages.count == cleared.count
&& groundImages.allSatisfy { cleared[$0.state.id] === $0.state }
if resent { return }
clearedStates = nil
}
let newIds = Set(groundImages.map { $0.id })
let oldIds = Set(groundImageStatesById.keys)
var newStatesById: [String: GroundImageState] = [:]
Expand Down Expand Up @@ -116,10 +129,23 @@ final class MapboxGroundImageController: SlottedOverlayController {
}
}

/// `clearOverlays()` 用。描画済みの画像を外して空にする(地図と renderer は残す)。
///
/// コアの GroundImageController を継承していないので、他の種類と同じ `clear()` をここで持つ。
/// 空の一式を styleGate へ渡すので、スタイル読み込み前でも後でも、読み込み直しても戻らない。
func clear() async {
groundImageSubscriptions.values.forEach { $0.cancel() }
groundImageSubscriptions.removeAll()
clearedStates = groundImageStatesById
groundImageStatesById.removeAll()
styleGate.submit([])
}

func unbind() {
groundImageSubscriptions.values.forEach { $0.cancel() }
groundImageSubscriptions.removeAll()
groundImageStatesById.removeAll()
clearedStates = nil
styleGate.reset()
renderer.unbind()
groundImageManager.destroy()
Expand Down