mirror of
https://github.com/xweiba/location-spoofer.git
synced 2026-09-21 22:30:46 +08:00
merge: integrate complete MapKit runtime refresh
# Conflicts: # App/MapHomeView.swift # Shared/CoordinateConverter.swift # Tests/PaopaoLocationSpooferTests/FavoriteLocationStoreTests.swift # Tests/map_refactor_contract_test.sh
This commit is contained in:
@@ -85,6 +85,13 @@ enum CoordinateConverter {
|
||||
let current: MapCoordinateSystem
|
||||
}
|
||||
|
||||
enum RuntimeMapCoordinateSystemRefreshResult: Equatable {
|
||||
case unchanged(MapCoordinateSystem)
|
||||
case changed(MapCoordinateSystemChange)
|
||||
case unavailable(reason: String)
|
||||
case cancelled
|
||||
}
|
||||
|
||||
/// 当前 Apple 地图坐标标准。检测不可用时使用国内 GCJ-02 作为兜底。
|
||||
@MainActor static var currentMapCoordinateSystem = MapCoordinateSystem.gcj02
|
||||
@MainActor private static var mapCoordinateSystemCheckPending = false
|
||||
@@ -110,7 +117,7 @@ enum CoordinateConverter {
|
||||
let nextType: MapCoordinateSystem
|
||||
switch await fixedAnchorCoordinateSystemProbe() {
|
||||
case let .response(name, count):
|
||||
nextType = mapCoordinateSystem(anchorName: name)
|
||||
nextType = mapCoordinateSystem(forFixedAnchorFirstResultName: name)
|
||||
initialMapCoordinateSystemUsedFallback = false
|
||||
RuntimeLogger.info("APP", "坐标转换", "地图坐标标准检测获得明确结果", details: [
|
||||
"首条名称": name,
|
||||
@@ -146,7 +153,7 @@ enum CoordinateConverter {
|
||||
return currentMapCoordinateSystem
|
||||
}
|
||||
|
||||
_ = applyDetectedMapCoordinateSystem(nextType)
|
||||
currentMapCoordinateSystem = nextType
|
||||
RuntimeLogger.info("APP", "坐标转换", "地图坐标标准已确定,允许创建地图", details: [
|
||||
"最终标准": nextType.rawValue,
|
||||
"使用兜底": String(initialMapCoordinateSystemUsedFallback),
|
||||
@@ -155,64 +162,77 @@ enum CoordinateConverter {
|
||||
return nextType
|
||||
}
|
||||
|
||||
/// Re-runs the same location-independent fixed-anchor probe after a
|
||||
/// spoofing environment change. Runtime callers must never infer MapKit's
|
||||
/// representation from the geographic region of the current location: that
|
||||
/// sample may itself already be virtual.
|
||||
/// Re-runs the fixed-anchor MapKit behavior probe while the map is alive.
|
||||
/// Runtime failures preserve the last confirmed type: a potentially spoofed
|
||||
/// Core Location sample is not authoritative for MapKit's representation.
|
||||
@MainActor
|
||||
static func refreshMapCoordinateSystem() async -> MapCoordinateSystemChange? {
|
||||
static func refreshRuntimeMapCoordinateSystem(reason: String) async -> RuntimeMapCoordinateSystemRefreshResult {
|
||||
guard !mapCoordinateSystemCheckPending else {
|
||||
RuntimeLogger.info("APP", "坐标转换", "运行期地图坐标标准刷新已在进行中")
|
||||
return nil
|
||||
RuntimeLogger.info("APP", "坐标转换", "地图坐标标准运行期检测合并到进行中请求", details: [
|
||||
"触发原因": reason,
|
||||
"当前标准": currentMapCoordinateSystem.rawValue
|
||||
])
|
||||
return .unchanged(currentMapCoordinateSystem)
|
||||
}
|
||||
mapCoordinateSystemCheckPending = true
|
||||
defer { mapCoordinateSystemCheckPending = false }
|
||||
|
||||
RuntimeLogger.info("APP", "坐标转换", "运行期地图坐标标准刷新开始", details: [
|
||||
"当前标准": currentMapCoordinateSystem.rawValue,
|
||||
"锚点": "22.283819,114.158439"
|
||||
let previous = currentMapCoordinateSystem
|
||||
RuntimeLogger.info("APP", "坐标转换", "地图坐标标准运行期检测开始", details: [
|
||||
"触发原因": reason,
|
||||
"检测前标准": previous.rawValue,
|
||||
"锚点": "22.283819,114.158439",
|
||||
"缓存": "false"
|
||||
])
|
||||
|
||||
switch await fixedAnchorCoordinateSystemProbe() {
|
||||
case let .response(name, count):
|
||||
let detected = mapCoordinateSystem(anchorName: name)
|
||||
guard !Task.isCancelled else {
|
||||
RuntimeLogger.info("APP", "坐标转换", "地图坐标标准运行期检测结果已过期,取消写入", details: [
|
||||
"触发原因": reason,
|
||||
"保留标准": previous.rawValue
|
||||
])
|
||||
return .cancelled
|
||||
}
|
||||
let detected = mapCoordinateSystem(forFixedAnchorFirstResultName: name)
|
||||
initialMapCoordinateSystemUsedFallback = false
|
||||
let change = applyDetectedMapCoordinateSystem(detected)
|
||||
RuntimeLogger.info("APP", "坐标转换", "运行期地图坐标标准刷新完成", details: [
|
||||
guard detected != previous else {
|
||||
RuntimeLogger.info("APP", "坐标转换", "地图坐标标准运行期检测完成,标准未变化", details: [
|
||||
"触发原因": reason,
|
||||
"首条名称": name,
|
||||
"结果数": String(count),
|
||||
"确认标准": detected.rawValue
|
||||
])
|
||||
return .unchanged(detected)
|
||||
}
|
||||
let change = MapCoordinateSystemChange(previous: previous, current: detected)
|
||||
currentMapCoordinateSystem = detected
|
||||
RuntimeLogger.warning("APP", "坐标转换", "地图坐标标准运行期检测发现切换", details: [
|
||||
"触发原因": reason,
|
||||
"首条名称": name,
|
||||
"结果数": String(count),
|
||||
"探测标准": detected.rawValue,
|
||||
"发生切换": String(change != nil)
|
||||
"from": previous.rawValue,
|
||||
"to": detected.rawValue
|
||||
])
|
||||
return change
|
||||
case .unavailable(let reason), .timedOut(let reason):
|
||||
RuntimeLogger.warning("APP", "坐标转换", "运行期地图坐标标准刷新不可用,保留当前标准", details: [
|
||||
"原因": reason,
|
||||
"当前标准": currentMapCoordinateSystem.rawValue
|
||||
return .changed(change)
|
||||
case .unavailable(let failureReason), .timedOut(let failureReason):
|
||||
RuntimeLogger.warning("APP", "坐标转换", "地图坐标标准运行期检测失败,保留当前标准", details: [
|
||||
"触发原因": reason,
|
||||
"原因": failureReason,
|
||||
"保留标准": previous.rawValue
|
||||
])
|
||||
return nil
|
||||
return .unavailable(reason: failureReason)
|
||||
case .cancelled:
|
||||
RuntimeLogger.info("APP", "坐标转换", "运行期地图坐标标准刷新被取消,保留当前标准", details: [
|
||||
"当前标准": currentMapCoordinateSystem.rawValue
|
||||
RuntimeLogger.info("APP", "坐标转换", "地图坐标标准运行期检测已取消", details: [
|
||||
"触发原因": reason,
|
||||
"保留标准": previous.rawValue
|
||||
])
|
||||
return nil
|
||||
return .cancelled
|
||||
}
|
||||
}
|
||||
|
||||
/// Applies a coordinate system that was resolved by the fixed-anchor
|
||||
/// probe. Kept as a small deterministic seam for regression tests.
|
||||
@MainActor
|
||||
static func applyDetectedMapCoordinateSystem(_ detected: MapCoordinateSystem) -> MapCoordinateSystemChange? {
|
||||
guard detected != currentMapCoordinateSystem else { return nil }
|
||||
let change = MapCoordinateSystemChange(
|
||||
previous: currentMapCoordinateSystem,
|
||||
current: detected
|
||||
)
|
||||
currentMapCoordinateSystem = detected
|
||||
return change
|
||||
}
|
||||
|
||||
private static func mapCoordinateSystem(anchorName: String) -> MapCoordinateSystem {
|
||||
anchorName == "林士街" ? .gcj02 : .wgs84
|
||||
static func mapCoordinateSystem(forFixedAnchorFirstResultName name: String) -> MapCoordinateSystem {
|
||||
name == "林士街" ? .gcj02 : .wgs84
|
||||
}
|
||||
|
||||
/// A user-requested realtime sample is WGS-84 and can correct a provisional
|
||||
@@ -227,12 +247,14 @@ enum CoordinateConverter {
|
||||
return nil
|
||||
}
|
||||
let next: MapCoordinateSystem = usesGCJ02ServiceArea(lat: coordinate.latitude, lon: coordinate.longitude) ? .gcj02 : .wgs84
|
||||
guard let change = applyDetectedMapCoordinateSystem(next) else {
|
||||
guard next != currentMapCoordinateSystem else {
|
||||
RuntimeLogger.info("APP", "坐标转换", "实时定位确认兜底地图坐标标准无需修正", details: [
|
||||
"当前标准": currentMapCoordinateSystem.rawValue
|
||||
])
|
||||
return nil
|
||||
}
|
||||
let change = MapCoordinateSystemChange(previous: currentMapCoordinateSystem, current: next)
|
||||
currentMapCoordinateSystem = next
|
||||
RuntimeLogger.warning("APP", "坐标转换", "实时定位修正启动兜底地图坐标标准", details: [
|
||||
"from": change.previous.rawValue,
|
||||
"to": change.current.rawValue
|
||||
|
||||
@@ -116,11 +116,24 @@ final class FavoriteLocationStore: ObservableObject {
|
||||
mapCoordinateSystem: CoordinateConverter.MapCoordinateSystem,
|
||||
accuracy: Int
|
||||
) -> FavoriteLocation {
|
||||
let favorite = FavoriteLocation(
|
||||
name: name,
|
||||
coordinatePair: .init(mapCoordinate: mapCoordinate, mapCoordinateSystem: mapCoordinateSystem),
|
||||
accuracy: accuracy
|
||||
save(
|
||||
FavoriteLocation(
|
||||
name: name,
|
||||
coordinatePair: .init(mapCoordinate: mapCoordinate, mapCoordinateSystem: mapCoordinateSystem),
|
||||
accuracy: accuracy
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
/// Saves a coordinate pair whose source representation was already typed
|
||||
/// before an asynchronous map-coordinate-system refresh.
|
||||
@discardableResult
|
||||
func save(name: String, coordinatePair: CoordinatePair, accuracy: Int) -> FavoriteLocation {
|
||||
save(FavoriteLocation(name: name, coordinatePair: coordinatePair, accuracy: accuracy))
|
||||
}
|
||||
|
||||
@discardableResult
|
||||
private func save(_ favorite: FavoriteLocation) -> FavoriteLocation {
|
||||
favorites.removeAll {
|
||||
abs($0.coordinatePair.wgs84.latitude - favorite.coordinatePair.wgs84.latitude) < 0.000001
|
||||
&& abs($0.coordinatePair.wgs84.longitude - favorite.coordinatePair.wgs84.longitude) < 0.000001
|
||||
|
||||
Reference in New Issue
Block a user